1 /* 2 * Copyright (C) 2016 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 17 import java.lang.reflect.Method; 18 import java.lang.reflect.InvocationTargetException; 19 20 import dalvik.system.PathClassLoader; 21 22 // ClassLoader not delegating for non java. packages. 23 class DelegateLastPathClassLoader extends PathClassLoader { 24 DelegateLastPathClassLoader(String dexPath, ClassLoader parent)25 public DelegateLastPathClassLoader(String dexPath, ClassLoader parent) { 26 super(dexPath, parent); 27 } 28 29 @Override loadClass(String name, boolean resolve)30 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 31 if (!name.startsWith("java.")) { 32 try { 33 return findClass(name); 34 } catch (ClassNotFoundException ignore) { 35 // Ignore and fall through to parent class loader. 36 } 37 } 38 return super.loadClass(name, resolve); 39 } 40 } 41 42 public class Main { 43 main(String[] args)44 public static void main(String[] args) throws Exception { 45 System.loadLibrary(args[0]); 46 final String DEX_FILE = System.getenv("DEX_LOCATION") + "/613-inlining-dex-cache-ex.jar"; 47 ClassLoader loader = new DelegateLastPathClassLoader(DEX_FILE, Main.class.getClassLoader()); 48 Class cls = loader.loadClass("LoadedByAppClassLoader"); 49 Method m = cls.getDeclaredMethod("letMeInlineYou"); 50 // Invoke the method enough times to get JITted. 51 for (int i = 0; i < 10000; ++i) { 52 m.invoke(null); 53 } 54 ensureJitCompiled(cls, "letMeInlineYou"); 55 ClassLoader bLoader = areYouB(); 56 if (bLoader != Main.class.getClassLoader()) { 57 throw new Error("Wrong class loader"); 58 } 59 } 60 foo(Main o)61 public static void foo(Main o) { 62 // LoadedByAppClassLoader.letMeInlineYou will try to inline this 63 // method but used to pass the wrong class loader. As a result, 64 // the lookup of B.foo was updating the dex cache with the other 65 // class loader's B class. 66 if (o != null) { 67 o.myField.foo(); 68 } 69 } 70 71 public B myField; 72 areYouB()73 public static ClassLoader areYouB() { 74 return OtherClass.getB().getClassLoader(); 75 } 76 ensureJitCompiled(Class cls, String method_name)77 public static native void ensureJitCompiled(Class cls, String method_name); 78 } 79 80 class OtherClass { getB()81 public static Class getB() { 82 // This used to return the B class of another class loader. 83 return B.class; 84 } 85 } 86