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 try { 76 Class<?> badClass = Main.class.getClassLoader().loadClass("B"); 77 System.out.println("Loaded class B."); 78 badClass.newInstance(); 79 System.out.println("Should not be able to instantiate B with bad dex bytecode."); 80 } catch (VerifyError e) { 81 System.out.println("Caught VerifyError."); 82 } 83 84 // Make sure the same error is rethrown when reloading the bad class. 85 try { 86 Class<?> badClass = Main.class.getClassLoader().loadClass("B"); 87 System.out.println("Loaded class B."); 88 badClass.newInstance(); 89 System.out.println("Should not be able to instantiate B with bad dex bytecode."); 90 } catch (NoClassDefFoundError e) { 91 if (e.getCause() instanceof VerifyError) { 92 System.out.println("Caught wrapped VerifyError."); 93 } else { 94 e.printStackTrace(System.out); 95 } 96 } 97 98 System.out.println("Everything OK."); 99 } 100 } 101