blob: b633a0c22e2b7cad5ed8eb9aa12b06e0d2a42b81 [file] [log] [blame]
Alexey Grebenkinbe4c2bd2018-02-01 19:09:59 +03001/*
2 * Copyright (C) 2018 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.InvocationHandler;
19import java.lang.reflect.Constructor;
20import java.lang.reflect.Method;
21
22public class Main {
23 static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/616-cha-unloading-ex.jar";
24 static final String LIBRARY_SEARCH_PATH = System.getProperty("java.library.path");
25 static Constructor<? extends ClassLoader> sConstructor;
26
27 private static class CHAUnloaderRetType {
28 private CHAUnloaderRetType(WeakReference<ClassLoader> cl,
29 AbstractCHATester obj,
30 long methodPtr) {
31 this.cl = cl;
32 this.obj = obj;
33 this.methodPtr = methodPtr;
34 }
35 public WeakReference<ClassLoader> cl;
36 public AbstractCHATester obj;
37 public long methodPtr;
38 }
39
40 public static void main(String[] args) throws Exception {
41 System.loadLibrary(args[0]);
42
43 Class<ClassLoader> pathClassLoader = (Class<ClassLoader>) Class.forName("dalvik.system.PathClassLoader");
44 sConstructor =
45 pathClassLoader.getDeclaredConstructor(String.class, String.class, ClassLoader.class);
46
47 testUnload();
48 }
49
50 private static void testUnload() throws Exception {
51 // Load a concrete class, then unload it. Get a deleted ArtMethod to test if it'll be inlined.
52 CHAUnloaderRetType result = doUnloadLoader();
53 WeakReference<ClassLoader> loader = result.cl;
54 long methodPtr = result.methodPtr;
55 // Check that the classloader is indeed unloaded.
56 System.out.println(loader.get());
57
58 // Reuse the linear alloc so old pointers so it becomes invalid.
59 boolean ret = tryReuseArenaOfMethod(methodPtr, 10);
60 // Check that we indeed reused it.
61 System.out.println(ret);
62
63 // Try to JIT-compile under dangerous conditions.
64 ensureJitCompiled(Main.class, "targetMethodForJit");
65 System.out.println("Done");
66 }
67
68 private static void doUnloading() {
69 // Do multiple GCs to prevent rare flakiness if some other thread is keeping the
70 // classloader live.
71 for (int i = 0; i < 5; ++i) {
72 Runtime.getRuntime().gc();
73 }
74 }
75
76 private static CHAUnloaderRetType setupLoader()
77 throws Exception {
78 ClassLoader loader = sConstructor.newInstance(
79 DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader());
80 Class<?> concreteCHATester = loader.loadClass("ConcreteCHATester");
81
82 // Preemptively compile methods to prevent delayed JIT tasks from blocking the unloading.
83 ensureJitCompiled(concreteCHATester, "<init>");
84 ensureJitCompiled(concreteCHATester, "lonelyMethod");
85
86 Object obj = concreteCHATester.newInstance();
87 Method lonelyMethod = concreteCHATester.getDeclaredMethod("lonelyMethod");
88
89 // Get a pointer to a region that shall be not used after the unloading.
90 long artMethod = getArtMethod(lonelyMethod);
91
92 AbstractCHATester ret = null;
93 return new CHAUnloaderRetType(new WeakReference(loader), ret, artMethod);
94 }
95
96 private static CHAUnloaderRetType targetMethodForJit(int mode)
97 throws Exception {
98 CHAUnloaderRetType ret = new CHAUnloaderRetType(null, null, 0);
99 if (mode == 0) {
100 ret = setupLoader();
101 } else if (mode == 1) {
102 // This branch is not supposed to be executed. It shall trigger "lonelyMethod" inlining
103 // during jit compilation of "targetMethodForJit".
104 ret = setupLoader();
105 AbstractCHATester obj = ret.obj;
106 obj.lonelyMethod();
107 }
108 return ret;
109 }
110
111 private static CHAUnloaderRetType doUnloadLoader()
112 throws Exception {
113 CHAUnloaderRetType result = targetMethodForJit(0);
114 doUnloading();
115 return result;
116 }
117
118 private static native void ensureJitCompiled(Class<?> itf, String method_name);
119 private static native long getArtMethod(Object javaMethod);
120 private static native boolean tryReuseArenaOfMethod(long artMethod, int tries_count);
121}