xref: /aosp_15_r20/external/javassist/src/test/test/javassist/proxy/ProxyCacheGCTest.java (revision f1fbf3c2ab775ce834e0af96b7a85bdc7a0eac65)
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