You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
4.3 KiB
122 lines
4.3 KiB
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import java.lang.ref.WeakReference;
|
|
import java.lang.reflect.InvocationHandler;
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Method;
|
|
|
|
public class Main {
|
|
static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/616-cha-unloading-ex.jar";
|
|
static final String LIBRARY_SEARCH_PATH = System.getProperty("java.library.path");
|
|
static Constructor<? extends ClassLoader> sConstructor;
|
|
|
|
private static class CHAUnloaderRetType {
|
|
private CHAUnloaderRetType(WeakReference<ClassLoader> cl,
|
|
AbstractCHATester obj,
|
|
long methodPtr) {
|
|
this.cl = cl;
|
|
this.obj = obj;
|
|
this.methodPtr = methodPtr;
|
|
}
|
|
public WeakReference<ClassLoader> cl;
|
|
public AbstractCHATester obj;
|
|
public long methodPtr;
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
System.loadLibrary(args[0]);
|
|
|
|
Class<ClassLoader> pathClassLoader = (Class<ClassLoader>) Class.forName("dalvik.system.PathClassLoader");
|
|
sConstructor =
|
|
pathClassLoader.getDeclaredConstructor(String.class, String.class, ClassLoader.class);
|
|
|
|
testUnload();
|
|
}
|
|
|
|
private static void testUnload() throws Exception {
|
|
// Load a concrete class, then unload it. Get a deleted ArtMethod to test if it'll be inlined.
|
|
CHAUnloaderRetType result = doUnloadLoader();
|
|
WeakReference<ClassLoader> loader = result.cl;
|
|
long methodPtr = result.methodPtr;
|
|
// Check that the classloader is indeed unloaded.
|
|
if (loader.get() != null) {
|
|
throw new Error("Expected class loader to be unloaded");
|
|
}
|
|
|
|
// Reuse the linear alloc used by the unloaded class loader.
|
|
reuseArenaOfMethod(methodPtr);
|
|
|
|
// Try to JIT-compile under dangerous conditions.
|
|
ensureJitCompiled(Main.class, "targetMethodForJit");
|
|
System.out.println("Done");
|
|
}
|
|
|
|
private static void doUnloading() {
|
|
// Do multiple GCs to prevent rare flakiness if some other thread is keeping the
|
|
// classloader live.
|
|
for (int i = 0; i < 5; ++i) {
|
|
Runtime.getRuntime().gc();
|
|
}
|
|
}
|
|
|
|
private static CHAUnloaderRetType setupLoader()
|
|
throws Exception {
|
|
ClassLoader loader = sConstructor.newInstance(
|
|
DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader());
|
|
Class<?> concreteCHATester = loader.loadClass("ConcreteCHATester");
|
|
|
|
// Preemptively compile methods to prevent delayed JIT tasks from blocking the unloading.
|
|
ensureJitCompiled(concreteCHATester, "<init>");
|
|
ensureJitCompiled(concreteCHATester, "lonelyMethod");
|
|
|
|
Object obj = concreteCHATester.newInstance();
|
|
Method lonelyMethod = concreteCHATester.getDeclaredMethod("lonelyMethod");
|
|
|
|
// Get a pointer to a region that shall be not used after the unloading.
|
|
long artMethod = getArtMethod(lonelyMethod);
|
|
|
|
AbstractCHATester ret = null;
|
|
return new CHAUnloaderRetType(new WeakReference(loader), ret, artMethod);
|
|
}
|
|
|
|
private static CHAUnloaderRetType targetMethodForJit(int mode)
|
|
throws Exception {
|
|
CHAUnloaderRetType ret = new CHAUnloaderRetType(null, null, 0);
|
|
if (mode == 0) {
|
|
ret = setupLoader();
|
|
} else if (mode == 1) {
|
|
// This branch is not supposed to be executed. It shall trigger "lonelyMethod" inlining
|
|
// during jit compilation of "targetMethodForJit".
|
|
ret = setupLoader();
|
|
AbstractCHATester obj = ret.obj;
|
|
obj.lonelyMethod();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
private static CHAUnloaderRetType doUnloadLoader()
|
|
throws Exception {
|
|
CHAUnloaderRetType result = targetMethodForJit(0);
|
|
doUnloading();
|
|
return result;
|
|
}
|
|
|
|
private static native void ensureJitCompiled(Class<?> itf, String method_name);
|
|
private static native long getArtMethod(Object javaMethod);
|
|
private static native void reuseArenaOfMethod(long artMethod);
|
|
}
|