diff options
author | adinn <adinn@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2010-03-09 16:56:02 +0000 |
---|---|---|
committer | adinn <adinn@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2010-03-09 16:56:02 +0000 |
commit | 702704c3d5ad074271f7decf535205a360722ddf (patch) | |
tree | e31c3dff2420e992e0c6d78f59a9192feaa15f57 /src/test | |
parent | 8828594b4d4f3df5d14a5506fd74b6a1bec8ed2d (diff) | |
download | javassist-702704c3d5ad074271f7decf535205a360722ddf.tar.gz javassist-702704c3d5ad074271f7decf535205a360722ddf.zip |
fixed potential strong cyclic reference from proxy cache entries back to their class loader -- fixes JASSIST-104
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@517 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/test/javassist/proxy/ProxyCacheGCTest.java | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/test/test/javassist/proxy/ProxyCacheGCTest.java b/src/test/test/javassist/proxy/ProxyCacheGCTest.java new file mode 100644 index 00000000..8f583a37 --- /dev/null +++ b/src/test/test/javassist/proxy/ProxyCacheGCTest.java @@ -0,0 +1,116 @@ +package test.javassist.proxy; + +import javassist.*; +import javassist.util.proxy.MethodFilter; +import javassist.util.proxy.MethodHandler; +import javassist.util.proxy.ProxyFactory; +import junit.framework.TestCase; + +/** + * test which checks that proxy classes are not retained after their classloader is released. + * this is a before and after test which validates JASSIST-104 + */ +public class ProxyCacheGCTest extends TestCase +{ + /** + * creates a large number of proxies in separate classloaders then lets go of the classloaders and + * forces a GC. If we run out of heap then we know there is a problem. + */ + + public final static int REPETITION_COUNT = 10000; + private ClassPool basePool; + private CtClass baseHandler; + private CtClass baseFilter; + + protected void setUp() + { + basePool = ClassPool.getDefault(); + try { + baseHandler = basePool.get("javassist.util.proxy.MethodHandler"); + baseFilter = basePool.get("javassist.util.proxy.MethodFilter"); + } catch (NotFoundException e) { + e.printStackTrace(); + fail("could not find class " + e); + } + } + + public void testCacheGC() + { + ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); + ProxyFactory.useCache = false; + for (int i = 0; i < REPETITION_COUNT; i++) { + ClassLoader newCL = new TestLoader(); + try { + Thread.currentThread().setContextClassLoader(newCL); + createProxy(i); + } finally { + Thread.currentThread().setContextClassLoader(oldCL); + } + } + } + + /** + * called when a specific classloader is in place on the thread to create a method handler, method filter + * and proxy in the current loader and then + */ + public void createProxy(int counter) + { + try { + ClassPool classPool = new ClassPool(basePool); + + // create a target class in the current class loader + String targetName = "test.javassist.MyTarget_" + counter; + String targetConstructorName = "MyTarget_" + counter; + CtClass ctTargetClass = classPool.makeClass(targetName); + CtMethod targetMethod = CtNewMethod.make("public Object test() { return this; }", ctTargetClass); + ctTargetClass.addMethod(targetMethod); + CtConstructor targetConstructor = CtNewConstructor.make("public " + targetConstructorName + "() { }", ctTargetClass); + ctTargetClass.addConstructor(targetConstructor); + + // create a handler in the current classloader + String handlerName = "test.javassist.MyHandler_" + counter; + CtClass ctHandlerClass = classPool.makeClass(handlerName); + ctHandlerClass.addInterface(baseHandler); + 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); + ctHandlerClass.addMethod(handlerInvoke); + + // create a filter in the current classloader + String filterName = "test.javassist.MyFilter" + counter; + CtClass ctFilterClass = classPool.makeClass(filterName); + ctFilterClass.addInterface(baseFilter); + CtMethod filterIsHandled = CtNewMethod.make("public boolean isHandled(java.lang.reflect.Method m) { return true; }", ctFilterClass); + ctFilterClass.addMethod(filterIsHandled); + + // now create a proxyfactory and use it to create a proxy + + ProxyFactory factory = new ProxyFactory(); + Class javaTargetClass = classPool.toClass(ctTargetClass); + Class javaHandlerClass = classPool.toClass(ctHandlerClass); + Class javaFilterClass = classPool.toClass(ctFilterClass); + + MethodHandler handler= (MethodHandler)javaHandlerClass.newInstance(); + MethodFilter filter = (MethodFilter)javaFilterClass.newInstance(); + + // ok, now create a factory and a proxy class and proxy from that factory + factory.setHandler(handler); + factory.setFilter(filter); + factory.setSuperclass(javaTargetClass); + // factory.setSuperclass(Object.class); + + Class proxyClass = factory.createClass(); + Object target = proxyClass.newInstance(); + } catch (Exception e) { + e.printStackTrace(); + fail("cannot create proxy " + e); + } + + } + + /** + * a classloader which inherits from the system class loader and within which a proxy handler, + * filter and proxy will be located. + */ + public static class TestLoader extends ClassLoader + { + } +} |