1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import java.io.BufferedReader; 18*795d594fSAndroid Build Coastguard Worker import java.io.File; 19*795d594fSAndroid Build Coastguard Worker import java.io.FileReader; 20*795d594fSAndroid Build Coastguard Worker import java.lang.ref.WeakReference; 21*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Constructor; 22*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method; 23*795d594fSAndroid Build Coastguard Worker import java.nio.ByteBuffer; 24*795d594fSAndroid Build Coastguard Worker import java.util.Arrays; 25*795d594fSAndroid Build Coastguard Worker import java.util.function.Consumer; 26*795d594fSAndroid Build Coastguard Worker import java.util.Base64; 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker public class Main { 29*795d594fSAndroid Build Coastguard Worker static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/141-class-unload-ex.jar"; 30*795d594fSAndroid Build Coastguard Worker static final String LIBRARY_SEARCH_PATH = System.getProperty("java.library.path"); 31*795d594fSAndroid Build Coastguard Worker static String nativeLibraryName; 32*795d594fSAndroid Build Coastguard Worker main(String[] args)33*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 34*795d594fSAndroid Build Coastguard Worker nativeLibraryName = args[0]; 35*795d594fSAndroid Build Coastguard Worker Class<?> pathClassLoader = Class.forName("dalvik.system.PathClassLoader"); 36*795d594fSAndroid Build Coastguard Worker if (pathClassLoader == null) { 37*795d594fSAndroid Build Coastguard Worker throw new AssertionError("Couldn't find path class loader class"); 38*795d594fSAndroid Build Coastguard Worker } 39*795d594fSAndroid Build Coastguard Worker Constructor<?> constructor = 40*795d594fSAndroid Build Coastguard Worker pathClassLoader.getDeclaredConstructor(String.class, String.class, ClassLoader.class); 41*795d594fSAndroid Build Coastguard Worker try { 42*795d594fSAndroid Build Coastguard Worker testUnloadClass(constructor); 43*795d594fSAndroid Build Coastguard Worker testUnloadLoader(constructor); 44*795d594fSAndroid Build Coastguard Worker // Test that we don't unload if we have an instance. 45*795d594fSAndroid Build Coastguard Worker testNoUnloadInstance(constructor); 46*795d594fSAndroid Build Coastguard Worker // Test JNI_OnLoad and JNI_OnUnload. 47*795d594fSAndroid Build Coastguard Worker testLoadAndUnloadLibrary(constructor); 48*795d594fSAndroid Build Coastguard Worker // Test that stack traces keep the classes live. 49*795d594fSAndroid Build Coastguard Worker testStackTrace(constructor); 50*795d594fSAndroid Build Coastguard Worker // Stress test to make sure we dont leak memory. 51*795d594fSAndroid Build Coastguard Worker stressTest(constructor); 52*795d594fSAndroid Build Coastguard Worker // Test that the oat files are unloaded. 53*795d594fSAndroid Build Coastguard Worker testOatFilesUnloaded(getPid()); 54*795d594fSAndroid Build Coastguard Worker // Test that objects keep class loader live for sticky GC. 55*795d594fSAndroid Build Coastguard Worker testStickyUnload(constructor); 56*795d594fSAndroid Build Coastguard Worker // Test that copied methods recorded in a stack trace prevents unloading. 57*795d594fSAndroid Build Coastguard Worker testCopiedMethodInStackTrace(constructor); 58*795d594fSAndroid Build Coastguard Worker // Test that code preventing unloading holder classes of copied methods recorded in 59*795d594fSAndroid Build Coastguard Worker // a stack trace does not crash when processing a copied method in the boot class path. 60*795d594fSAndroid Build Coastguard Worker testCopiedBcpMethodInStackTrace(); 61*795d594fSAndroid Build Coastguard Worker // Test that code preventing unloading holder classes of copied methods recorded in 62*795d594fSAndroid Build Coastguard Worker // a stack trace does not crash when processing a copied method in an app image. 63*795d594fSAndroid Build Coastguard Worker testCopiedAppImageMethodInStackTrace(); 64*795d594fSAndroid Build Coastguard Worker // Test that the runtime uses the right allocator when creating conflict methods. 65*795d594fSAndroid Build Coastguard Worker testConflictMethod(constructor); 66*795d594fSAndroid Build Coastguard Worker testConflictMethod2(constructor); 67*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 68*795d594fSAndroid Build Coastguard Worker e.printStackTrace(System.out); 69*795d594fSAndroid Build Coastguard Worker } 70*795d594fSAndroid Build Coastguard Worker } 71*795d594fSAndroid Build Coastguard Worker testOatFilesUnloaded(int pid)72*795d594fSAndroid Build Coastguard Worker private static void testOatFilesUnloaded(int pid) throws Exception { 73*795d594fSAndroid Build Coastguard Worker System.loadLibrary(nativeLibraryName); 74*795d594fSAndroid Build Coastguard Worker // Stop the JIT to ensure its threads and work queue are not keeping classes 75*795d594fSAndroid Build Coastguard Worker // artifically alive. 76*795d594fSAndroid Build Coastguard Worker stopJit(); 77*795d594fSAndroid Build Coastguard Worker doUnloading(); 78*795d594fSAndroid Build Coastguard Worker System.runFinalization(); 79*795d594fSAndroid Build Coastguard Worker BufferedReader reader = new BufferedReader(new FileReader ("/proc/" + pid + "/maps")); 80*795d594fSAndroid Build Coastguard Worker String line; 81*795d594fSAndroid Build Coastguard Worker int count = 0; 82*795d594fSAndroid Build Coastguard Worker while ((line = reader.readLine()) != null) { 83*795d594fSAndroid Build Coastguard Worker if (line.contains("141-class-unload-ex.odex") || 84*795d594fSAndroid Build Coastguard Worker line.contains("141-class-unload-ex.vdex")) { 85*795d594fSAndroid Build Coastguard Worker System.out.println(line); 86*795d594fSAndroid Build Coastguard Worker ++count; 87*795d594fSAndroid Build Coastguard Worker } 88*795d594fSAndroid Build Coastguard Worker } 89*795d594fSAndroid Build Coastguard Worker System.out.println("Number of loaded unload-ex maps " + count); 90*795d594fSAndroid Build Coastguard Worker startJit(); 91*795d594fSAndroid Build Coastguard Worker } 92*795d594fSAndroid Build Coastguard Worker stressTest(Constructor<?> constructor)93*795d594fSAndroid Build Coastguard Worker private static void stressTest(Constructor<?> constructor) throws Exception { 94*795d594fSAndroid Build Coastguard Worker for (int i = 0; i <= 100; ++i) { 95*795d594fSAndroid Build Coastguard Worker setUpUnloadLoader(constructor, false); 96*795d594fSAndroid Build Coastguard Worker if (i % 10 == 0) { 97*795d594fSAndroid Build Coastguard Worker Runtime.getRuntime().gc(); 98*795d594fSAndroid Build Coastguard Worker } 99*795d594fSAndroid Build Coastguard Worker } 100*795d594fSAndroid Build Coastguard Worker } 101*795d594fSAndroid Build Coastguard Worker doUnloading()102*795d594fSAndroid Build Coastguard Worker private static void doUnloading() { 103*795d594fSAndroid Build Coastguard Worker // Do multiple GCs to prevent rare flakiness if some other thread is keeping the 104*795d594fSAndroid Build Coastguard Worker // classloader live. 105*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 5; ++i) { 106*795d594fSAndroid Build Coastguard Worker Runtime.getRuntime().gc(); 107*795d594fSAndroid Build Coastguard Worker } 108*795d594fSAndroid Build Coastguard Worker } 109*795d594fSAndroid Build Coastguard Worker testUnloadClass(Constructor<?> constructor)110*795d594fSAndroid Build Coastguard Worker private static void testUnloadClass(Constructor<?> constructor) throws Exception { 111*795d594fSAndroid Build Coastguard Worker WeakReference<Class> klass = setUpUnloadClassWeak(constructor); 112*795d594fSAndroid Build Coastguard Worker // No strong references to class loader, should get unloaded. 113*795d594fSAndroid Build Coastguard Worker doUnloading(); 114*795d594fSAndroid Build Coastguard Worker WeakReference<Class> klass2 = setUpUnloadClassWeak(constructor); 115*795d594fSAndroid Build Coastguard Worker doUnloading(); 116*795d594fSAndroid Build Coastguard Worker // If the weak reference is cleared, then it was unloaded. 117*795d594fSAndroid Build Coastguard Worker System.out.println(klass.get()); 118*795d594fSAndroid Build Coastguard Worker System.out.println(klass2.get()); 119*795d594fSAndroid Build Coastguard Worker } 120*795d594fSAndroid Build Coastguard Worker testUnloadLoader(Constructor<?> constructor)121*795d594fSAndroid Build Coastguard Worker private static void testUnloadLoader(Constructor<?> constructor) throws Exception { 122*795d594fSAndroid Build Coastguard Worker WeakReference<ClassLoader> loader = setUpUnloadLoader(constructor, true); 123*795d594fSAndroid Build Coastguard Worker // No strong references to class loader, should get unloaded. 124*795d594fSAndroid Build Coastguard Worker doUnloading(); 125*795d594fSAndroid Build Coastguard Worker // If the weak reference is cleared, then it was unloaded. 126*795d594fSAndroid Build Coastguard Worker System.out.println(loader.get()); 127*795d594fSAndroid Build Coastguard Worker } 128*795d594fSAndroid Build Coastguard Worker testStackTrace(Constructor<?> constructor)129*795d594fSAndroid Build Coastguard Worker private static void testStackTrace(Constructor<?> constructor) throws Exception { 130*795d594fSAndroid Build Coastguard Worker Class<?> klass = setUpUnloadClass(constructor); 131*795d594fSAndroid Build Coastguard Worker WeakReference<Class> weak_klass = new WeakReference(klass); 132*795d594fSAndroid Build Coastguard Worker Method stackTraceMethod = klass.getDeclaredMethod("generateStackTrace"); 133*795d594fSAndroid Build Coastguard Worker Throwable throwable = (Throwable) stackTraceMethod.invoke(klass); 134*795d594fSAndroid Build Coastguard Worker stackTraceMethod = null; 135*795d594fSAndroid Build Coastguard Worker klass = null; 136*795d594fSAndroid Build Coastguard Worker doUnloading(); 137*795d594fSAndroid Build Coastguard Worker boolean isNull = weak_klass.get() == null; 138*795d594fSAndroid Build Coastguard Worker System.out.println("class null " + isNull + " " + throwable.getMessage()); 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker testLoadAndUnloadLibrary(Constructor<?> constructor)141*795d594fSAndroid Build Coastguard Worker private static void testLoadAndUnloadLibrary(Constructor<?> constructor) throws Exception { 142*795d594fSAndroid Build Coastguard Worker WeakReference<ClassLoader> loader = setUpLoadLibrary(constructor); 143*795d594fSAndroid Build Coastguard Worker // No strong references to class loader, should get unloaded. 144*795d594fSAndroid Build Coastguard Worker doUnloading(); 145*795d594fSAndroid Build Coastguard Worker // If the weak reference is cleared, then it was unloaded. 146*795d594fSAndroid Build Coastguard Worker System.out.println(loader.get()); 147*795d594fSAndroid Build Coastguard Worker } 148*795d594fSAndroid Build Coastguard Worker testNoUnloadHelper(ClassLoader loader)149*795d594fSAndroid Build Coastguard Worker private static Object testNoUnloadHelper(ClassLoader loader) throws Exception { 150*795d594fSAndroid Build Coastguard Worker Class<?> intHolder = loader.loadClass("IntHolder"); 151*795d594fSAndroid Build Coastguard Worker return intHolder.newInstance(); 152*795d594fSAndroid Build Coastguard Worker } 153*795d594fSAndroid Build Coastguard Worker 154*795d594fSAndroid Build Coastguard Worker static class Pair { Pair(Object o, ClassLoader l)155*795d594fSAndroid Build Coastguard Worker public Pair(Object o, ClassLoader l) { 156*795d594fSAndroid Build Coastguard Worker object = o; 157*795d594fSAndroid Build Coastguard Worker classLoader = new WeakReference<ClassLoader>(l); 158*795d594fSAndroid Build Coastguard Worker } 159*795d594fSAndroid Build Coastguard Worker 160*795d594fSAndroid Build Coastguard Worker public Object object; 161*795d594fSAndroid Build Coastguard Worker public WeakReference<ClassLoader> classLoader; 162*795d594fSAndroid Build Coastguard Worker } 163*795d594fSAndroid Build Coastguard Worker 164*795d594fSAndroid Build Coastguard Worker // Make the method not inline-able to prevent the compiler optimizing away the allocation. $noinline$testNoUnloadInstanceHelper(Constructor<?> constructor)165*795d594fSAndroid Build Coastguard Worker private static Pair $noinline$testNoUnloadInstanceHelper(Constructor<?> constructor) 166*795d594fSAndroid Build Coastguard Worker throws Exception { 167*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 168*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader()); 169*795d594fSAndroid Build Coastguard Worker Object o = testNoUnloadHelper(loader); 170*795d594fSAndroid Build Coastguard Worker return new Pair(o, loader); 171*795d594fSAndroid Build Coastguard Worker } 172*795d594fSAndroid Build Coastguard Worker testNoUnloadInstance(Constructor<?> constructor)173*795d594fSAndroid Build Coastguard Worker private static void testNoUnloadInstance(Constructor<?> constructor) throws Exception { 174*795d594fSAndroid Build Coastguard Worker Pair p = $noinline$testNoUnloadInstanceHelper(constructor); 175*795d594fSAndroid Build Coastguard Worker doUnloading(); 176*795d594fSAndroid Build Coastguard Worker boolean isNull = p.classLoader.get() == null; 177*795d594fSAndroid Build Coastguard Worker System.out.println("loader null " + isNull); 178*795d594fSAndroid Build Coastguard Worker } 179*795d594fSAndroid Build Coastguard Worker setUpUnloadClass(Constructor<?> constructor)180*795d594fSAndroid Build Coastguard Worker private static Class<?> setUpUnloadClass(Constructor<?> constructor) throws Exception { 181*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 182*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader()); 183*795d594fSAndroid Build Coastguard Worker Class<?> intHolder = loader.loadClass("IntHolder"); 184*795d594fSAndroid Build Coastguard Worker Method getValue = intHolder.getDeclaredMethod("getValue"); 185*795d594fSAndroid Build Coastguard Worker Method setValue = intHolder.getDeclaredMethod("setValue", Integer.TYPE); 186*795d594fSAndroid Build Coastguard Worker // Make sure we don't accidentally preserve the value in the int holder, the class 187*795d594fSAndroid Build Coastguard Worker // initializer should be re-run. 188*795d594fSAndroid Build Coastguard Worker System.out.println((int) getValue.invoke(intHolder)); 189*795d594fSAndroid Build Coastguard Worker setValue.invoke(intHolder, 2); 190*795d594fSAndroid Build Coastguard Worker System.out.println((int) getValue.invoke(intHolder)); 191*795d594fSAndroid Build Coastguard Worker waitForCompilation(intHolder); 192*795d594fSAndroid Build Coastguard Worker return intHolder; 193*795d594fSAndroid Build Coastguard Worker } 194*795d594fSAndroid Build Coastguard Worker allocObjectInOtherClassLoader(Constructor<?> constructor)195*795d594fSAndroid Build Coastguard Worker private static Object allocObjectInOtherClassLoader(Constructor<?> constructor) 196*795d594fSAndroid Build Coastguard Worker throws Exception { 197*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 198*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader()); 199*795d594fSAndroid Build Coastguard Worker return loader.loadClass("IntHolder").newInstance(); 200*795d594fSAndroid Build Coastguard Worker } 201*795d594fSAndroid Build Coastguard Worker 202*795d594fSAndroid Build Coastguard Worker // Regression test for public issue 227182. testStickyUnload(Constructor<?> constructor)203*795d594fSAndroid Build Coastguard Worker private static void testStickyUnload(Constructor<?> constructor) throws Exception { 204*795d594fSAndroid Build Coastguard Worker String s = ""; 205*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) { 206*795d594fSAndroid Build Coastguard Worker s = ""; 207*795d594fSAndroid Build Coastguard Worker // The object is the only thing preventing the class loader from being unloaded. 208*795d594fSAndroid Build Coastguard Worker Object o = allocObjectInOtherClassLoader(constructor); 209*795d594fSAndroid Build Coastguard Worker for (int j = 0; j < 1000; ++j) { 210*795d594fSAndroid Build Coastguard Worker s += j + " "; 211*795d594fSAndroid Build Coastguard Worker } 212*795d594fSAndroid Build Coastguard Worker // Make sure the object still has a valid class (hasn't been incorrectly unloaded). 213*795d594fSAndroid Build Coastguard Worker s += o.getClass().getName(); 214*795d594fSAndroid Build Coastguard Worker o = null; 215*795d594fSAndroid Build Coastguard Worker } 216*795d594fSAndroid Build Coastguard Worker System.out.println("Too small " + (s.length() < 1000)); 217*795d594fSAndroid Build Coastguard Worker } 218*795d594fSAndroid Build Coastguard Worker assertStackTraceContains(Throwable t, String className, String methodName)219*795d594fSAndroid Build Coastguard Worker private static void assertStackTraceContains(Throwable t, String className, String methodName) { 220*795d594fSAndroid Build Coastguard Worker boolean found = false; 221*795d594fSAndroid Build Coastguard Worker for (StackTraceElement e : t.getStackTrace()) { 222*795d594fSAndroid Build Coastguard Worker if (className.equals(e.getClassName()) && methodName.equals(e.getMethodName())) { 223*795d594fSAndroid Build Coastguard Worker found = true; 224*795d594fSAndroid Build Coastguard Worker break; 225*795d594fSAndroid Build Coastguard Worker } 226*795d594fSAndroid Build Coastguard Worker } 227*795d594fSAndroid Build Coastguard Worker if (!found) { 228*795d594fSAndroid Build Coastguard Worker throw new Error("Did not find " + className + "." + methodName); 229*795d594fSAndroid Build Coastguard Worker } 230*795d594fSAndroid Build Coastguard Worker } 231*795d594fSAndroid Build Coastguard Worker $noinline$callAllMethods(ConflictIface iface)232*795d594fSAndroid Build Coastguard Worker private static void $noinline$callAllMethods(ConflictIface iface) { 233*795d594fSAndroid Build Coastguard Worker // Call all methods in the interface to make sure we hit conflicts in the IMT. 234*795d594fSAndroid Build Coastguard Worker iface.method1(); 235*795d594fSAndroid Build Coastguard Worker iface.method2(); 236*795d594fSAndroid Build Coastguard Worker iface.method3(); 237*795d594fSAndroid Build Coastguard Worker iface.method4(); 238*795d594fSAndroid Build Coastguard Worker iface.method5(); 239*795d594fSAndroid Build Coastguard Worker iface.method6(); 240*795d594fSAndroid Build Coastguard Worker iface.method7(); 241*795d594fSAndroid Build Coastguard Worker iface.method8(); 242*795d594fSAndroid Build Coastguard Worker iface.method9(); 243*795d594fSAndroid Build Coastguard Worker iface.method10(); 244*795d594fSAndroid Build Coastguard Worker iface.method11(); 245*795d594fSAndroid Build Coastguard Worker iface.method12(); 246*795d594fSAndroid Build Coastguard Worker iface.method13(); 247*795d594fSAndroid Build Coastguard Worker iface.method14(); 248*795d594fSAndroid Build Coastguard Worker iface.method15(); 249*795d594fSAndroid Build Coastguard Worker iface.method16(); 250*795d594fSAndroid Build Coastguard Worker iface.method17(); 251*795d594fSAndroid Build Coastguard Worker iface.method18(); 252*795d594fSAndroid Build Coastguard Worker iface.method19(); 253*795d594fSAndroid Build Coastguard Worker iface.method20(); 254*795d594fSAndroid Build Coastguard Worker iface.method21(); 255*795d594fSAndroid Build Coastguard Worker iface.method22(); 256*795d594fSAndroid Build Coastguard Worker iface.method23(); 257*795d594fSAndroid Build Coastguard Worker iface.method24(); 258*795d594fSAndroid Build Coastguard Worker iface.method25(); 259*795d594fSAndroid Build Coastguard Worker iface.method26(); 260*795d594fSAndroid Build Coastguard Worker iface.method27(); 261*795d594fSAndroid Build Coastguard Worker iface.method28(); 262*795d594fSAndroid Build Coastguard Worker iface.method29(); 263*795d594fSAndroid Build Coastguard Worker iface.method30(); 264*795d594fSAndroid Build Coastguard Worker iface.method31(); 265*795d594fSAndroid Build Coastguard Worker iface.method32(); 266*795d594fSAndroid Build Coastguard Worker iface.method33(); 267*795d594fSAndroid Build Coastguard Worker iface.method34(); 268*795d594fSAndroid Build Coastguard Worker iface.method35(); 269*795d594fSAndroid Build Coastguard Worker iface.method36(); 270*795d594fSAndroid Build Coastguard Worker iface.method37(); 271*795d594fSAndroid Build Coastguard Worker iface.method38(); 272*795d594fSAndroid Build Coastguard Worker iface.method39(); 273*795d594fSAndroid Build Coastguard Worker iface.method40(); 274*795d594fSAndroid Build Coastguard Worker iface.method41(); 275*795d594fSAndroid Build Coastguard Worker iface.method42(); 276*795d594fSAndroid Build Coastguard Worker iface.method43(); 277*795d594fSAndroid Build Coastguard Worker iface.method44(); 278*795d594fSAndroid Build Coastguard Worker iface.method45(); 279*795d594fSAndroid Build Coastguard Worker iface.method46(); 280*795d594fSAndroid Build Coastguard Worker iface.method47(); 281*795d594fSAndroid Build Coastguard Worker iface.method48(); 282*795d594fSAndroid Build Coastguard Worker iface.method49(); 283*795d594fSAndroid Build Coastguard Worker iface.method50(); 284*795d594fSAndroid Build Coastguard Worker iface.method51(); 285*795d594fSAndroid Build Coastguard Worker iface.method52(); 286*795d594fSAndroid Build Coastguard Worker iface.method53(); 287*795d594fSAndroid Build Coastguard Worker iface.method54(); 288*795d594fSAndroid Build Coastguard Worker iface.method55(); 289*795d594fSAndroid Build Coastguard Worker iface.method56(); 290*795d594fSAndroid Build Coastguard Worker iface.method57(); 291*795d594fSAndroid Build Coastguard Worker iface.method58(); 292*795d594fSAndroid Build Coastguard Worker iface.method59(); 293*795d594fSAndroid Build Coastguard Worker iface.method60(); 294*795d594fSAndroid Build Coastguard Worker iface.method61(); 295*795d594fSAndroid Build Coastguard Worker iface.method62(); 296*795d594fSAndroid Build Coastguard Worker iface.method63(); 297*795d594fSAndroid Build Coastguard Worker iface.method64(); 298*795d594fSAndroid Build Coastguard Worker iface.method65(); 299*795d594fSAndroid Build Coastguard Worker iface.method66(); 300*795d594fSAndroid Build Coastguard Worker iface.method67(); 301*795d594fSAndroid Build Coastguard Worker iface.method68(); 302*795d594fSAndroid Build Coastguard Worker iface.method69(); 303*795d594fSAndroid Build Coastguard Worker iface.method70(); 304*795d594fSAndroid Build Coastguard Worker iface.method71(); 305*795d594fSAndroid Build Coastguard Worker iface.method72(); 306*795d594fSAndroid Build Coastguard Worker iface.method73(); 307*795d594fSAndroid Build Coastguard Worker iface.method74(); 308*795d594fSAndroid Build Coastguard Worker iface.method75(); 309*795d594fSAndroid Build Coastguard Worker iface.method76(); 310*795d594fSAndroid Build Coastguard Worker iface.method77(); 311*795d594fSAndroid Build Coastguard Worker iface.method78(); 312*795d594fSAndroid Build Coastguard Worker iface.method79(); 313*795d594fSAndroid Build Coastguard Worker } 314*795d594fSAndroid Build Coastguard Worker $noinline$invokeConflictMethod(Constructor<?> constructor)315*795d594fSAndroid Build Coastguard Worker private static void $noinline$invokeConflictMethod(Constructor<?> constructor) 316*795d594fSAndroid Build Coastguard Worker throws Exception { 317*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 318*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader()); 319*795d594fSAndroid Build Coastguard Worker Class<?> impl = loader.loadClass("ConflictImpl"); 320*795d594fSAndroid Build Coastguard Worker ConflictIface iface = (ConflictIface) impl.newInstance(); 321*795d594fSAndroid Build Coastguard Worker $noinline$callAllMethods(iface); 322*795d594fSAndroid Build Coastguard Worker } 323*795d594fSAndroid Build Coastguard Worker testConflictMethod(Constructor<?> constructor)324*795d594fSAndroid Build Coastguard Worker private static void testConflictMethod(Constructor<?> constructor) throws Exception { 325*795d594fSAndroid Build Coastguard Worker // Load and unload a few class loaders to force re-use of the native memory where we 326*795d594fSAndroid Build Coastguard Worker // used to allocate the conflict table. 327*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) { 328*795d594fSAndroid Build Coastguard Worker $noinline$invokeConflictMethod(constructor); 329*795d594fSAndroid Build Coastguard Worker doUnloading(); 330*795d594fSAndroid Build Coastguard Worker } 331*795d594fSAndroid Build Coastguard Worker Class<?> impl = Class.forName("ConflictSuper"); 332*795d594fSAndroid Build Coastguard Worker ConflictIface iface = (ConflictIface) impl.newInstance(); 333*795d594fSAndroid Build Coastguard Worker $noinline$callAllMethods(iface); 334*795d594fSAndroid Build Coastguard Worker } 335*795d594fSAndroid Build Coastguard Worker $noinline$invokeConflictMethod2(Constructor<?> constructor)336*795d594fSAndroid Build Coastguard Worker private static void $noinline$invokeConflictMethod2(Constructor<?> constructor) 337*795d594fSAndroid Build Coastguard Worker throws Exception { 338*795d594fSAndroid Build Coastguard Worker // We need three class loaders to expose the issue: the main one with the top super class, 339*795d594fSAndroid Build Coastguard Worker // then a second one with the abstract class which we used to wrongly return as an IMT 340*795d594fSAndroid Build Coastguard Worker // owner, and the concrete class in a different class loader. 341*795d594fSAndroid Build Coastguard Worker Class<?> cls = Class.forName("dalvik.system.InMemoryDexClassLoader"); 342*795d594fSAndroid Build Coastguard Worker Constructor<?> inMemoryConstructor = 343*795d594fSAndroid Build Coastguard Worker cls.getDeclaredConstructor(ByteBuffer.class, ClassLoader.class); 344*795d594fSAndroid Build Coastguard Worker ClassLoader inMemoryLoader = (ClassLoader) inMemoryConstructor.newInstance( 345*795d594fSAndroid Build Coastguard Worker ByteBuffer.wrap(DEX_BYTES), ClassLoader.getSystemClassLoader()); 346*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 347*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, inMemoryLoader); 348*795d594fSAndroid Build Coastguard Worker Class<?> impl = loader.loadClass("ConflictImpl2"); 349*795d594fSAndroid Build Coastguard Worker ConflictIface iface = (ConflictIface) impl.newInstance(); 350*795d594fSAndroid Build Coastguard Worker $noinline$callAllMethods(iface); 351*795d594fSAndroid Build Coastguard Worker } 352*795d594fSAndroid Build Coastguard Worker testConflictMethod2(Constructor<?> constructor)353*795d594fSAndroid Build Coastguard Worker private static void testConflictMethod2(Constructor<?> constructor) throws Exception { 354*795d594fSAndroid Build Coastguard Worker // Load and unload a few class loaders to force re-use of the native memory where we 355*795d594fSAndroid Build Coastguard Worker // used to allocate the conflict table. 356*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) { 357*795d594fSAndroid Build Coastguard Worker $noinline$invokeConflictMethod2(constructor); 358*795d594fSAndroid Build Coastguard Worker doUnloading(); 359*795d594fSAndroid Build Coastguard Worker } 360*795d594fSAndroid Build Coastguard Worker Class<?> impl = Class.forName("ConflictSuper"); 361*795d594fSAndroid Build Coastguard Worker ConflictIface iface = (ConflictIface) impl.newInstance(); 362*795d594fSAndroid Build Coastguard Worker $noinline$callAllMethods(iface); 363*795d594fSAndroid Build Coastguard Worker } 364*795d594fSAndroid Build Coastguard Worker testCopiedMethodInStackTrace(Constructor<?> constructor)365*795d594fSAndroid Build Coastguard Worker private static void testCopiedMethodInStackTrace(Constructor<?> constructor) throws Exception { 366*795d594fSAndroid Build Coastguard Worker Throwable t = $noinline$createStackTraceWithCopiedMethod(constructor); 367*795d594fSAndroid Build Coastguard Worker doUnloading(); 368*795d594fSAndroid Build Coastguard Worker assertStackTraceContains(t, "Iface", "invokeRun"); 369*795d594fSAndroid Build Coastguard Worker } 370*795d594fSAndroid Build Coastguard Worker $noinline$createStackTraceWithCopiedMethod(Constructor<?> constructor)371*795d594fSAndroid Build Coastguard Worker private static Throwable $noinline$createStackTraceWithCopiedMethod(Constructor<?> constructor) 372*795d594fSAndroid Build Coastguard Worker throws Exception { 373*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 374*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, Main.class.getClassLoader()); 375*795d594fSAndroid Build Coastguard Worker Iface impl = (Iface) loader.loadClass("Impl").newInstance(); 376*795d594fSAndroid Build Coastguard Worker Runnable throwingRunnable = new Runnable() { 377*795d594fSAndroid Build Coastguard Worker public void run() { 378*795d594fSAndroid Build Coastguard Worker throw new Error(); 379*795d594fSAndroid Build Coastguard Worker } 380*795d594fSAndroid Build Coastguard Worker }; 381*795d594fSAndroid Build Coastguard Worker try { 382*795d594fSAndroid Build Coastguard Worker impl.invokeRun(throwingRunnable); 383*795d594fSAndroid Build Coastguard Worker System.out.println("UNREACHABLE"); 384*795d594fSAndroid Build Coastguard Worker return null; 385*795d594fSAndroid Build Coastguard Worker } catch (Error expected) { 386*795d594fSAndroid Build Coastguard Worker return expected; 387*795d594fSAndroid Build Coastguard Worker } 388*795d594fSAndroid Build Coastguard Worker } 389*795d594fSAndroid Build Coastguard Worker testCopiedBcpMethodInStackTrace()390*795d594fSAndroid Build Coastguard Worker private static void testCopiedBcpMethodInStackTrace() { 391*795d594fSAndroid Build Coastguard Worker Consumer<Object> consumer = new Consumer<Object>() { 392*795d594fSAndroid Build Coastguard Worker public void accept(Object o) { 393*795d594fSAndroid Build Coastguard Worker throw new Error(); 394*795d594fSAndroid Build Coastguard Worker } 395*795d594fSAndroid Build Coastguard Worker }; 396*795d594fSAndroid Build Coastguard Worker Error err = null; 397*795d594fSAndroid Build Coastguard Worker try { 398*795d594fSAndroid Build Coastguard Worker Arrays.asList(new Object[] { new Object() }).iterator().forEachRemaining(consumer); 399*795d594fSAndroid Build Coastguard Worker } catch (Error expected) { 400*795d594fSAndroid Build Coastguard Worker err = expected; 401*795d594fSAndroid Build Coastguard Worker } 402*795d594fSAndroid Build Coastguard Worker assertStackTraceContains(err, "Main", "testCopiedBcpMethodInStackTrace"); 403*795d594fSAndroid Build Coastguard Worker } 404*795d594fSAndroid Build Coastguard Worker testCopiedAppImageMethodInStackTrace()405*795d594fSAndroid Build Coastguard Worker private static void testCopiedAppImageMethodInStackTrace() throws Exception { 406*795d594fSAndroid Build Coastguard Worker Iface limpl = (Iface) Class.forName("Impl2").newInstance(); 407*795d594fSAndroid Build Coastguard Worker Runnable throwingRunnable = new Runnable() { 408*795d594fSAndroid Build Coastguard Worker public void run() { 409*795d594fSAndroid Build Coastguard Worker throw new Error(); 410*795d594fSAndroid Build Coastguard Worker } 411*795d594fSAndroid Build Coastguard Worker }; 412*795d594fSAndroid Build Coastguard Worker Error err = null; 413*795d594fSAndroid Build Coastguard Worker try { 414*795d594fSAndroid Build Coastguard Worker limpl.invokeRun(throwingRunnable); 415*795d594fSAndroid Build Coastguard Worker } catch (Error expected) { 416*795d594fSAndroid Build Coastguard Worker err = expected; 417*795d594fSAndroid Build Coastguard Worker } 418*795d594fSAndroid Build Coastguard Worker assertStackTraceContains(err, "Main", "testCopiedAppImageMethodInStackTrace"); 419*795d594fSAndroid Build Coastguard Worker } 420*795d594fSAndroid Build Coastguard Worker setUpUnloadClassWeak(Constructor<?> constructor)421*795d594fSAndroid Build Coastguard Worker private static WeakReference<Class> setUpUnloadClassWeak(Constructor<?> constructor) 422*795d594fSAndroid Build Coastguard Worker throws Exception { 423*795d594fSAndroid Build Coastguard Worker return new WeakReference<Class>(setUpUnloadClass(constructor)); 424*795d594fSAndroid Build Coastguard Worker } 425*795d594fSAndroid Build Coastguard Worker setUpUnloadLoader(Constructor<?> constructor, boolean waitForCompilation)426*795d594fSAndroid Build Coastguard Worker private static WeakReference<ClassLoader> setUpUnloadLoader(Constructor<?> constructor, 427*795d594fSAndroid Build Coastguard Worker boolean waitForCompilation) 428*795d594fSAndroid Build Coastguard Worker throws Exception { 429*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 430*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader()); 431*795d594fSAndroid Build Coastguard Worker Class<?> intHolder = loader.loadClass("IntHolder"); 432*795d594fSAndroid Build Coastguard Worker Method setValue = intHolder.getDeclaredMethod("setValue", Integer.TYPE); 433*795d594fSAndroid Build Coastguard Worker setValue.invoke(intHolder, 2); 434*795d594fSAndroid Build Coastguard Worker if (waitForCompilation) { 435*795d594fSAndroid Build Coastguard Worker waitForCompilation(intHolder); 436*795d594fSAndroid Build Coastguard Worker } 437*795d594fSAndroid Build Coastguard Worker return new WeakReference(loader); 438*795d594fSAndroid Build Coastguard Worker } 439*795d594fSAndroid Build Coastguard Worker waitForCompilation(Class<?> intHolder)440*795d594fSAndroid Build Coastguard Worker private static void waitForCompilation(Class<?> intHolder) throws Exception { 441*795d594fSAndroid Build Coastguard Worker // Load the native library so that we can call waitForCompilation. 442*795d594fSAndroid Build Coastguard Worker Method loadLibrary = intHolder.getDeclaredMethod("loadLibrary", String.class); 443*795d594fSAndroid Build Coastguard Worker loadLibrary.invoke(intHolder, nativeLibraryName); 444*795d594fSAndroid Build Coastguard Worker // Wait for JIT compilation to finish since the async threads may prevent unloading. 445*795d594fSAndroid Build Coastguard Worker Method waitForCompilation = intHolder.getDeclaredMethod("waitForCompilation"); 446*795d594fSAndroid Build Coastguard Worker waitForCompilation.invoke(intHolder); 447*795d594fSAndroid Build Coastguard Worker } 448*795d594fSAndroid Build Coastguard Worker setUpLoadLibrary(Constructor<?> constructor)449*795d594fSAndroid Build Coastguard Worker private static WeakReference<ClassLoader> setUpLoadLibrary(Constructor<?> constructor) 450*795d594fSAndroid Build Coastguard Worker throws Exception { 451*795d594fSAndroid Build Coastguard Worker ClassLoader loader = (ClassLoader) constructor.newInstance( 452*795d594fSAndroid Build Coastguard Worker DEX_FILE, LIBRARY_SEARCH_PATH, ClassLoader.getSystemClassLoader()); 453*795d594fSAndroid Build Coastguard Worker Class<?> intHolder = loader.loadClass("IntHolder"); 454*795d594fSAndroid Build Coastguard Worker Method loadLibrary = intHolder.getDeclaredMethod("loadLibrary", String.class); 455*795d594fSAndroid Build Coastguard Worker loadLibrary.invoke(intHolder, nativeLibraryName); 456*795d594fSAndroid Build Coastguard Worker waitForCompilation(intHolder); 457*795d594fSAndroid Build Coastguard Worker return new WeakReference(loader); 458*795d594fSAndroid Build Coastguard Worker } 459*795d594fSAndroid Build Coastguard Worker getPid()460*795d594fSAndroid Build Coastguard Worker private static int getPid() throws Exception { 461*795d594fSAndroid Build Coastguard Worker return Integer.parseInt(new File("/proc/self").getCanonicalFile().getName()); 462*795d594fSAndroid Build Coastguard Worker } 463*795d594fSAndroid Build Coastguard Worker stopJit()464*795d594fSAndroid Build Coastguard Worker public static native void stopJit(); startJit()465*795d594fSAndroid Build Coastguard Worker public static native void startJit(); 466*795d594fSAndroid Build Coastguard Worker 467*795d594fSAndroid Build Coastguard Worker 468*795d594fSAndroid Build Coastguard Worker /* Corresponds to: 469*795d594fSAndroid Build Coastguard Worker * 470*795d594fSAndroid Build Coastguard Worker * public abstract class AbstractClass extends ConflictSuper { } 471*795d594fSAndroid Build Coastguard Worker * 472*795d594fSAndroid Build Coastguard Worker */ 473*795d594fSAndroid Build Coastguard Worker private static final byte[] DEX_BYTES = Base64.getDecoder().decode( 474*795d594fSAndroid Build Coastguard Worker "ZGV4CjAzNQAOZ0WGvUad/2dEp77oyy9K2tx8txklUZ1wAgAAcAAAAHhWNBIAAAAAAAAAANwBAAAG" + 475*795d594fSAndroid Build Coastguard Worker "AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAIAAACgAAAAAQAAALAAAACgAQAA0AAAAOwA" + 476*795d594fSAndroid Build Coastguard Worker "AAD0AAAACAEAABkBAAAqAQAALQEAAAIAAAADAAAABAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAQAA" + 477*795d594fSAndroid Build Coastguard Worker "AAAAAAAAAAAAAQQAAAEAAAAAAAAAAQAAAAAAAADLAQAAAAAAAAEAAQABAAAA6AAAAAQAAABwEAEA" + 478*795d594fSAndroid Build Coastguard Worker "AAAOABEADgAGPGluaXQ+ABJBYnN0cmFjdENsYXNzLmphdmEAD0xBYnN0cmFjdENsYXNzOwAPTENv" + 479*795d594fSAndroid Build Coastguard Worker "bmZsaWN0U3VwZXI7AAFWAJsBfn5EOHsiYmFja2VuZCI6ImRleCIsImNvbXBpbGF0aW9uLW1vZGUi" + 480*795d594fSAndroid Build Coastguard Worker "OiJkZWJ1ZyIsImhhcy1jaGVja3N1bXMiOmZhbHNlLCJtaW4tYXBpIjoxLCJzaGEtMSI6ImI3MmIx" + 481*795d594fSAndroid Build Coastguard Worker "NWJjODQ2N2Y0M2FhNTdlYjk5ZDAyMjU0Nzg5ODYwZjRlOWEiLCJ2ZXJzaW9uIjoiOC41LjEtZGV2" + 482*795d594fSAndroid Build Coastguard Worker "In0AAAABAACBgATQAQAAAAAAAAAMAAAAAAAAAAEAAAAAAAAAAQAAAAYAAABwAAAAAgAAAAMAAACI" + 483*795d594fSAndroid Build Coastguard Worker "AAAAAwAAAAEAAACUAAAABQAAAAIAAACgAAAABgAAAAEAAACwAAAAASAAAAEAAADQAAAAAyAAAAEA" + 484*795d594fSAndroid Build Coastguard Worker "AADoAAAAAiAAAAYAAADsAAAAACAAAAEAAADLAQAAAxAAAAEAAADYAQAAABAAAAEAAADcAQAA"); 485*795d594fSAndroid Build Coastguard Worker } 486