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