package org.hotswap.agent.plugin.proxy.java; import org.hotswap.agent.logging.AgentLogger; import org.hotswap.agent.plugin.proxy.ParentLastClassLoader; import org.hotswap.agent.plugin.proxy.ProxyClassSignatureHelper; import org.hotswap.agent.plugin.proxy.ProxyTransformer; /** * Redefines Java proxy classes. One-step process. Uses Classes from a new classloader. * * @author Erki Ehtla * */ public class NewClassLoaderJavaProxyTransformer implements ProxyTransformer { /** * * @param classBeingRedefined * @param classfileBuffer * new definition of Class<?> * @param loader * classloader of classBeingRedefined * @return classfileBuffer or new Proxy defition if there are signature changes */ public NewClassLoaderJavaProxyTransformer(Class<?> classBeingRedefined, byte[] classfileBuffer, ClassLoader loader) { super(); this.classBeingRedefined = classBeingRedefined; this.classfileBuffer = classfileBuffer; this.loader = loader; } private static AgentLogger LOGGER = AgentLogger.getLogger(NewClassLoaderJavaProxyTransformer.class); private final Class<?> classBeingRedefined; private final byte[] classfileBuffer; private final ClassLoader loader; /** * * @param classBeingRedefined * @param classfileBuffer * new definition of Class<?> * @param loader * classloader of classBeingRedefined * @return classfileBuffer or new Proxy defition if there are signature changes * @throws Exception */ public static byte[] transform(final Class<?> classBeingRedefined, byte[] classfileBuffer, ClassLoader loader) throws Exception { return new NewClassLoaderJavaProxyTransformer(classBeingRedefined, classfileBuffer, loader).transformRedefine(); } @Override public byte[] transformRedefine() throws Exception { try { ParentLastClassLoader parentLastClassLoader = new ParentLastClassLoader(loader); Class<?>[] interfaces = classBeingRedefined.getInterfaces(); Class<?>[] newInterfaces = new Class[interfaces.length]; for (int i = 0; i < newInterfaces.length; i++) { newInterfaces[i] = parentLastClassLoader.loadClass(interfaces[i].getName()); } if (!ProxyClassSignatureHelper.isDifferent(interfaces, newInterfaces)) { return classfileBuffer; } Class<?> generatorClass = parentLastClassLoader.loadClass(ProxyGenerator.class.getName()); byte[] generateProxyClass = (byte[]) generatorClass.getDeclaredMethod("generateProxyClass", String.class, Class[].class).invoke(null, classBeingRedefined.getName(), newInterfaces); LOGGER.reload("Class '{}' has been reloaded.", classBeingRedefined.getName()); return generateProxyClass; } catch (Exception e) { LOGGER.error("Error transforming a Java reflect Proxy", e); return classfileBuffer; } } }