blob: da15746d1c1aa47ffe4f4f2b8915dfc285c432c8 [file] [log] [blame]
Mathieu Chartier05aa4d32015-09-19 12:44:38 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import java.lang.ref.WeakReference;
18import java.lang.reflect.Constructor;
19import java.lang.reflect.Method;
20
21public class Main {
22 static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/141-class-unload-ex.jar";
Mathieu Chartier598302a2015-09-23 14:52:39 -070023 static String nativeLibraryName;
Mathieu Chartier05aa4d32015-09-19 12:44:38 -070024
25 public static void main(String[] args) throws Exception {
Mathieu Chartier598302a2015-09-23 14:52:39 -070026 nativeLibraryName = args[0];
Mathieu Chartier05aa4d32015-09-19 12:44:38 -070027 Class pathClassLoader = Class.forName("dalvik.system.PathClassLoader");
28 if (pathClassLoader == null) {
29 throw new AssertionError("Couldn't find path class loader class");
30 }
31 Constructor constructor =
32 pathClassLoader.getDeclaredConstructor(String.class, ClassLoader.class);
33 try {
34 testUnloadClassAndLoader(constructor);
35 // Test that we don't unload if we have a Method keeping the class live.
36 testNoUnloadInvoke(constructor);
37 // Test that we don't unload if we have an instance.
38 testNoUnloadInstance(constructor);
Mathieu Chartier598302a2015-09-23 14:52:39 -070039 // Test JNI_OnLoad and JNI_OnUnload.
40 testLoadAndUnloadLibrary(constructor);
Mathieu Chartier05aa4d32015-09-19 12:44:38 -070041 // Stress test to make sure we dont leak memory.
42 stressTest(constructor);
43 } catch (Exception e) {
44 System.out.println(e);
45 }
46 }
47
48 private static void stressTest(Constructor constructor) throws Exception {
49 for (int i = 0; i <= 100; ++i) {
50 setUpUnloadLoader(constructor);
51 if (i % 10 == 0) {
52 Runtime.getRuntime().gc();
53 }
54 }
55 }
56
57 private static void testUnloadClassAndLoader(Constructor constructor) throws Exception {
58 WeakReference<ClassLoader> loader = setUpUnloadLoader(constructor);
59 WeakReference<Class> klass = setUpUnloadClass(constructor);
60 // No strong refernces to class loader, should get unloaded.
61 Runtime.getRuntime().gc();
62 WeakReference<Class> klass2 = setUpUnloadClass(constructor);
63 Runtime.getRuntime().gc();
64 // If the weak reference is cleared, then it was unloaded.
65 System.out.println(klass.get());
66 System.out.println(klass2.get());
67 System.out.println(loader.get());
68 }
69
Mathieu Chartier598302a2015-09-23 14:52:39 -070070 private static void testLoadAndUnloadLibrary(Constructor constructor) throws Exception {
71 WeakReference<ClassLoader> loader = setUpLoadLibrary(constructor);
72 // No strong refernces to class loader, should get unloaded.
73 Runtime.getRuntime().gc();
74 // If the weak reference is cleared, then it was unloaded.
75 System.out.println(loader.get());
76 }
77
Mathieu Chartier05aa4d32015-09-19 12:44:38 -070078 private static void testNoUnloadInvoke(Constructor constructor) throws Exception {
79 WeakReference<ClassLoader> loader =
80 new WeakReference((ClassLoader) constructor.newInstance(
81 DEX_FILE, ClassLoader.getSystemClassLoader()));
82 WeakReference<Class> intHolder = new WeakReference(loader.get().loadClass("IntHolder"));
83 intHolder.get().getDeclaredMethod("runGC").invoke(intHolder.get());
84 boolean isNull = loader.get() == null;
85 System.out.println("loader null " + isNull);
86 }
87
88 private static void testNoUnloadInstance(Constructor constructor) throws Exception {
89 WeakReference<ClassLoader> loader =
90 new WeakReference((ClassLoader) constructor.newInstance(
91 DEX_FILE, ClassLoader.getSystemClassLoader()));
92 WeakReference<Class> intHolder = new WeakReference(loader.get().loadClass("IntHolder"));
93 Object o = intHolder.get().newInstance();
94 Runtime.getRuntime().gc();
95 boolean isNull = loader.get() == null;
96 System.out.println("loader null " + isNull);
97 }
98
99 private static WeakReference<Class> setUpUnloadClass(Constructor constructor)
100 throws Exception {
101 ClassLoader loader = (ClassLoader) constructor.newInstance(
102 DEX_FILE, ClassLoader.getSystemClassLoader());
103 Class intHolder = loader.loadClass("IntHolder");
104 Method getValue = intHolder.getDeclaredMethod("getValue");
105 Method setValue = intHolder.getDeclaredMethod("setValue", Integer.TYPE);
106 // Make sure we don't accidentally preserve the value in the int holder, the class
107 // initializer should be re-run.
108 System.out.println((int) getValue.invoke(intHolder));
109 setValue.invoke(intHolder, 2);
110 System.out.println((int) getValue.invoke(intHolder));
111 return new WeakReference(intHolder);
112 }
113
114 private static WeakReference<ClassLoader> setUpUnloadLoader(Constructor constructor)
115 throws Exception {
116 ClassLoader loader = (ClassLoader) constructor.newInstance(
117 DEX_FILE, ClassLoader.getSystemClassLoader());
118 Class intHolder = loader.loadClass("IntHolder");
119 Method setValue = intHolder.getDeclaredMethod("setValue", Integer.TYPE);
120 setValue.invoke(intHolder, 2);
121 return new WeakReference(loader);
122 }
123
Mathieu Chartier598302a2015-09-23 14:52:39 -0700124 private static WeakReference<ClassLoader> setUpLoadLibrary(Constructor constructor)
125 throws Exception {
126 ClassLoader loader = (ClassLoader) constructor.newInstance(
127 DEX_FILE, ClassLoader.getSystemClassLoader());
128 Class intHolder = loader.loadClass("IntHolder");
129 Method setValue = intHolder.getDeclaredMethod("loadLibrary", String.class);
130 setValue.invoke(intHolder, nativeLibraryName);
131 return new WeakReference(loader);
132 }
Mathieu Chartier05aa4d32015-09-19 12:44:38 -0700133}