1 /* 2 * Copyright (C) 2015 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.Constructor; 18 import java.lang.reflect.Field; 19 20 /** 21 * PathClassLoader test. 22 */ 23 public class Main { 24 createClassLoader(String dexPath, ClassLoader parent)25 private static ClassLoader createClassLoader(String dexPath, ClassLoader parent) { 26 try { 27 Class<?> myClassLoaderClass = Class.forName("MyPathClassLoader"); 28 Constructor<?> constructor = myClassLoaderClass.getConstructor(String.class, 29 ClassLoader.class); 30 return (ClassLoader)constructor.newInstance(dexPath, parent); 31 } catch (Exception e) { 32 // Ups, not available?!?! 33 throw new RuntimeException(e); 34 } 35 } 36 37 /** 38 * Main entry point. 39 */ main(String[] args)40 public static void main(String[] args) throws Exception { 41 // Check the class-path for the second file. We'll use that one as the source of the 42 // new classloader. 43 String cp = System.getProperty("java.class.path"); 44 if (cp.split(System.getProperty("path.separator")).length != 1) { 45 throw new IllegalStateException("Didn't find exactly one classpath element in " + cp); 46 } 47 if (!cp.endsWith("classloader2.jar")) { 48 throw new IllegalStateException("Don't understand classpath " + cp); 49 } 50 cp = cp.replace("classloader2.jar", "classloader2-ex.jar"); 51 52 ClassLoader myClassLoader = createClassLoader( 53 cp, ClassLoader.getSystemClassLoader().getParent()); 54 55 // Now load our test class. 56 Class<?> srcClass = A.class; 57 Class<?> exClass = myClassLoader.loadClass("A"); 58 59 // First check: classes should be different. 60 if (srcClass == exClass) { 61 throw new IllegalStateException("Loaded class instances are the same"); 62 } 63 64 // Secondary checks: get the static field values and make sure they aren't the same. 65 String srcValue = (String)srcClass.getDeclaredField("value").get(null); 66 if (!"Src-A".equals(srcValue)) { 67 throw new IllegalStateException("Expected Src-A, found " + srcValue); 68 } 69 String exValue = (String)exClass.getDeclaredField("value").get(null); 70 if (!"Ex-A".equals(exValue)) { 71 throw new IllegalStateException("Expected Ex-A, found " + exValue); 72 } 73 74 // Try to load a dex file with bad dex code. Use new instance to force verification. 75 VerifyError existing = null; 76 try { 77 Class<?> badClass = Main.class.getClassLoader().loadClass("B"); 78 System.out.println("Loaded class B."); 79 badClass.newInstance(); 80 System.out.println("Should not be able to instantiate B with bad dex bytecode."); 81 } catch (VerifyError e) { 82 System.out.println("Caught VerifyError."); 83 existing = e; 84 } 85 86 // Make sure the same error is rethrown when reloading the bad class. 87 try { 88 Class<?> badClass = Main.class.getClassLoader().loadClass("B"); 89 System.out.println("Loaded class B."); 90 badClass.newInstance(); 91 System.out.println("Should not be able to instantiate B with bad dex bytecode."); 92 } catch (VerifyError e) { 93 if (e == existing) { 94 System.out.println("Caught existing VerifyError."); 95 } else { 96 e.printStackTrace(System.out); 97 } 98 } 99 100 System.out.println("Everything OK."); 101 } 102 } 103