diff options
Diffstat (limited to 'test/497-inlining-and-class-loader/src/Main.java')
-rw-r--r-- | test/497-inlining-and-class-loader/src/Main.java | 198 |
1 files changed, 99 insertions, 99 deletions
diff --git a/test/497-inlining-and-class-loader/src/Main.java b/test/497-inlining-and-class-loader/src/Main.java index 01b4bcd391..66a3f6e785 100644 --- a/test/497-inlining-and-class-loader/src/Main.java +++ b/test/497-inlining-and-class-loader/src/Main.java @@ -19,112 +19,112 @@ import java.lang.reflect.Method; import java.util.List; class MyClassLoader extends ClassLoader { - MyClassLoader() throws Exception { - super(MyClassLoader.class.getClassLoader()); - - // Some magic to get access to the pathList field of BaseDexClassLoader. - ClassLoader loader = getClass().getClassLoader(); - Class<?> baseDexClassLoader = loader.getClass().getSuperclass(); - Field f = baseDexClassLoader.getDeclaredField("pathList"); - f.setAccessible(true); - Object pathList = f.get(loader); - - // Some magic to get access to the dexField field of pathList. - f = pathList.getClass().getDeclaredField("dexElements"); - f.setAccessible(true); - dexElements = (Object[]) f.get(pathList); - dexFileField = dexElements[0].getClass().getDeclaredField("dexFile"); - dexFileField.setAccessible(true); - } - - Object[] dexElements; - Field dexFileField; - - static ClassLoader level1ClassLoader; - - protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException { - if (this != level1ClassLoader) { - if (className.equals("Level1")) { - return level1ClassLoader.loadClass(className); - } else if (className.equals("Level2")) { - throw new ClassNotFoundException("None of my methods require Level2!"); - } else if (!className.equals("LoadedByMyClassLoader")) { - // We're only going to handle LoadedByMyClassLoader. - return getParent().loadClass(className); - } - } else { - if (className != "Level1" && className != "Level2") { - return getParent().loadClass(className); - } + MyClassLoader() throws Exception { + super(MyClassLoader.class.getClassLoader()); + + // Some magic to get access to the pathList field of BaseDexClassLoader. + ClassLoader loader = getClass().getClassLoader(); + Class<?> baseDexClassLoader = loader.getClass().getSuperclass(); + Field f = baseDexClassLoader.getDeclaredField("pathList"); + f.setAccessible(true); + Object pathList = f.get(loader); + + // Some magic to get access to the dexField field of pathList. + f = pathList.getClass().getDeclaredField("dexElements"); + f.setAccessible(true); + dexElements = (Object[]) f.get(pathList); + dexFileField = dexElements[0].getClass().getDeclaredField("dexFile"); + dexFileField.setAccessible(true); } - // Mimic what DexPathList.findClass is doing. - try { - for (Object element : dexElements) { - Object dex = dexFileField.get(element); - Method method = dex.getClass().getDeclaredMethod( - "loadClassBinaryName", String.class, ClassLoader.class, List.class); - - if (dex != null) { - Class<?> clazz = (Class<?>)method.invoke(dex, className, this, null); - if (clazz != null) { - return clazz; - } + Object[] dexElements; + Field dexFileField; + + static ClassLoader level1ClassLoader; + + protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException { + if (this != level1ClassLoader) { + if (className.equals("Level1")) { + return level1ClassLoader.loadClass(className); + } else if (className.equals("Level2")) { + throw new ClassNotFoundException("None of my methods require Level2!"); + } else if (!className.equals("LoadedByMyClassLoader")) { + // We're only going to handle LoadedByMyClassLoader. + return getParent().loadClass(className); + } + } else { + if (className != "Level1" && className != "Level2") { + return getParent().loadClass(className); + } } - } - } catch (Exception e) { /* Ignore */ } - return null; - } + + // Mimic what DexPathList.findClass is doing. + try { + for (Object element : dexElements) { + Object dex = dexFileField.get(element); + Method method = dex.getClass().getDeclaredMethod( + "loadClassBinaryName", String.class, ClassLoader.class, List.class); + + if (dex != null) { + Class<?> clazz = (Class<?>) method.invoke(dex, className, this, null); + if (clazz != null) { + return clazz; + } + } + } + } catch (Exception e) { /* Ignore */ } + return null; + } } class LoadedByMyClassLoader { - public static void bar() { - Level1.$inline$bar(); - } + public static void bar() { + Level1.$inline$bar(); + } } class Main { - public static void main(String[] args) throws Exception { - System.loadLibrary(args[0]); - // Clone resolved methods, to restore the original version just - // before we walk the stack in $noinline$bar. - savedResolvedMethods = cloneResolvedMethods(Main.class); - - MyClassLoader o = new MyClassLoader(); - MyClassLoader.level1ClassLoader = new MyClassLoader(); - Class<?> foo = o.loadClass("LoadedByMyClassLoader"); - Method m = foo.getDeclaredMethod("bar"); - try { - m.invoke(null); - } catch (Error e) { /* Ignore */ } - } - - public static void $inline$bar() { - } - - public static void $noinline$bar() { - try { - // Be evil and clear all dex cache entries. - Field f = Class.class.getDeclaredField("dexCache"); - f.setAccessible(true); - Object dexCache = f.get(Main.class); - f = dexCache.getClass().getDeclaredField("resolvedTypes"); - f.setAccessible(true); - Object[] array = (Object[]) f.get(dexCache); - for (int i = 0; i < array.length; i++) { - array[i] = null; - } - restoreResolvedMethods(Main.class, savedResolvedMethods); - } catch (Throwable t) { /* Ignore */ } - - // This will walk the stack, trying to resolve methods in it. - // Because we cleared dex cache entries, we will have to find - // classes again, which require to use the correct class loader - // in the presence of inlining. - new Exception().printStackTrace(System.out); - } - static Object savedResolvedMethods; - - static native Object cloneResolvedMethods(Class<?> cls); - static native void restoreResolvedMethods(Class<?> cls, Object saved); + public static void main(String[] args) throws Exception { + System.loadLibrary(args[0]); + // Clone resolved methods, to restore the original version just + // before we walk the stack in $noinline$bar. + savedResolvedMethods = cloneResolvedMethods(Main.class); + + MyClassLoader o = new MyClassLoader(); + MyClassLoader.level1ClassLoader = new MyClassLoader(); + Class<?> foo = o.loadClass("LoadedByMyClassLoader"); + Method m = foo.getDeclaredMethod("bar"); + try { + m.invoke(null); + } catch (Error e) { /* Ignore */ } + } + + public static void $inline$bar() { + } + + public static void $noinline$bar() { + try { + // Be evil and clear all dex cache entries. + Field f = Class.class.getDeclaredField("dexCache"); + f.setAccessible(true); + Object dexCache = f.get(Main.class); + f = dexCache.getClass().getDeclaredField("resolvedTypes"); + f.setAccessible(true); + Object[] array = (Object[]) f.get(dexCache); + for (int i = 0; i < array.length; i++) { + array[i] = null; + } + restoreResolvedMethods(Main.class, savedResolvedMethods); + } catch (Throwable t) { /* Ignore */ } + + // This will walk the stack, trying to resolve methods in it. + // Because we cleared dex cache entries, we will have to find + // classes again, which require to use the correct class loader + // in the presence of inlining. + new Exception().printStackTrace(System.out); + } + static Object savedResolvedMethods; + + static native Object cloneResolvedMethods(Class<?> cls); + static native void restoreResolvedMethods(Class<?> cls, Object saved); } |