summaryrefslogtreecommitdiffstats
path: root/src/test
diff options
context:
space:
mode:
authoradinn <adinn@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2010-03-09 16:56:02 +0000
committeradinn <adinn@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2010-03-09 16:56:02 +0000
commit702704c3d5ad074271f7decf535205a360722ddf (patch)
treee31c3dff2420e992e0c6d78f59a9192feaa15f57 /src/test
parent8828594b4d4f3df5d14a5506fd74b6a1bec8ed2d (diff)
downloadjavassist-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.java116
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
+ {
+ }
+}