1 package test.javassist.proxy; 2 3 import javassist.*; 4 import javassist.util.proxy.MethodFilter; 5 import javassist.util.proxy.MethodHandler; 6 import javassist.util.proxy.ProxyFactory; 7 import javassist.util.proxy.ProxyObject; 8 import junit.framework.TestCase; 9 10 /** 11 * test which checks that proxy classes are not retained after their classloader is released. 12 * this is a before and after test which validates JASSIST-104 13 */ 14 @SuppressWarnings({"rawtypes","unchecked"}) 15 public class ProxyCacheGCTest extends TestCase 16 { 17 /** 18 * creates a large number of proxies in separate classloaders then lets go of the classloaders and 19 * forces a GC. If we run out of heap then we know there is a problem. 20 */ 21 22 public final static int REPETITION_COUNT = 10000; 23 private ClassPool basePool; 24 private CtClass baseHandler; 25 private CtClass baseFilter; 26 setUp()27 protected void setUp() 28 { 29 basePool = ClassPool.getDefault(); 30 try { 31 baseHandler = basePool.get("javassist.util.proxy.MethodHandler"); 32 baseFilter = basePool.get("javassist.util.proxy.MethodFilter"); 33 } catch (NotFoundException e) { 34 e.printStackTrace(); 35 fail("could not find class " + e); 36 } 37 } 38 testCacheGC()39 public void testCacheGC() 40 { 41 ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); 42 try { 43 ProxyFactory.useCache = false; 44 for (int i = 0; i < REPETITION_COUNT; i++) { 45 ClassLoader newCL = new TestLoader(); 46 try { 47 Thread.currentThread().setContextClassLoader(newCL); 48 createProxy(i); 49 } finally { 50 Thread.currentThread().setContextClassLoader(oldCL); 51 } 52 } 53 } finally { 54 ProxyFactory.useCache = true; 55 } 56 } 57 58 /** 59 * called when a specific classloader is in place on the thread to create a method handler, method filter 60 * and proxy in the current loader and then 61 */ createProxy(int counter)62 public void createProxy(int counter) 63 { 64 try { 65 ClassPool classPool = new ClassPool(basePool); 66 67 // create a target class in the current class loader 68 String targetName = "test.javassist.MyTarget_" + counter; 69 String targetConstructorName = "MyTarget_" + counter; 70 CtClass ctTargetClass = classPool.makeClass(targetName); 71 CtMethod targetMethod = CtNewMethod.make("public Object test() { return this; }", ctTargetClass); 72 ctTargetClass.addMethod(targetMethod); 73 CtConstructor targetConstructor = CtNewConstructor.make("public " + targetConstructorName + "() { }", ctTargetClass); 74 ctTargetClass.addConstructor(targetConstructor); 75 76 // create a handler in the current classloader 77 String handlerName = "test.javassist.MyHandler_" + counter; 78 CtClass ctHandlerClass = classPool.makeClass(handlerName); 79 ctHandlerClass.addInterface(baseHandler); 80 CtMethod handlerInvoke = CtNewMethod.make("public Object invoke(Object self, java.lang.reflect.Method thisMethod, java.lang.reflect.Method proceed, Object[] args) throws Throwable { return proceed.invoke(self, args); }", ctHandlerClass); 81 ctHandlerClass.addMethod(handlerInvoke); 82 83 // create a filter in the current classloader 84 String filterName = "test.javassist.MyFilter" + counter; 85 CtClass ctFilterClass = classPool.makeClass(filterName); 86 ctFilterClass.addInterface(baseFilter); 87 CtMethod filterIsHandled = CtNewMethod.make("public boolean isHandled(java.lang.reflect.Method m) { return true; }", ctFilterClass); 88 ctFilterClass.addMethod(filterIsHandled); 89 90 // now create a proxyfactory and use it to create a proxy 91 92 ProxyFactory factory = new ProxyFactory(); 93 Class javaTargetClass = classPool.toClass(ctTargetClass, test.javassist.DefineClassCapability.class); 94 Class javaHandlerClass = classPool.toClass(ctHandlerClass, test.javassist.DefineClassCapability.class); 95 Class javaFilterClass = classPool.toClass(ctFilterClass, test.javassist.DefineClassCapability.class); 96 97 MethodHandler handler= (MethodHandler)javaHandlerClass.getConstructor().newInstance(); 98 MethodFilter filter = (MethodFilter)javaFilterClass.getConstructor().newInstance(); 99 100 // ok, now create a factory and a proxy class and proxy from that factory 101 factory.setFilter(filter); 102 factory.setSuperclass(javaTargetClass); 103 // factory.setSuperclass(Object.class); 104 105 Class proxyClass = factory.createClass(); 106 Object target = proxyClass.getConstructor().newInstance(); 107 ((ProxyObject)target).setHandler(handler); 108 } catch (Exception e) { 109 e.printStackTrace(); 110 fail("cannot create proxy " + e); 111 } 112 113 } 114 115 /** 116 * a classloader which inherits from the system class loader and within which a proxy handler, 117 * filter and proxy will be located. 118 */ 119 public static class TestLoader extends ClassLoader 120 { 121 } 122 } 123