1fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes/* 2fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Copyright (C) 2010 The Android Open Source Project 3fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 4fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Licensed under the Apache License, Version 2.0 (the "License"); 5fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * you may not use this file except in compliance with the License. 6fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * You may obtain a copy of the License at 7fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 8fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * http://www.apache.org/licenses/LICENSE-2.0 9fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 10fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Unless required by applicable law or agreed to in writing, software 11fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * distributed under the License is distributed on an "AS IS" BASIS, 12fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * See the License for the specific language governing permissions and 14fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * limitations under the License. 15fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 16fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 17fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayesimport java.lang.reflect.Constructor; 18fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayesimport java.lang.reflect.Method; 19fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayesimport java.lang.reflect.InvocationTargetException; 20fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 21fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes/** 22fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Class loader test. 23fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 24fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayespublic class Main { 2582b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes /** 2682b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * Thrown when an unexpected Exception is caught internally. 2782b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes */ 2882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes static class TestFailed extends Exception { 2982b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes public TestFailed(Throwable cause) { 3082b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes super(cause); 3182b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes } 3282b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes } 33fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 34fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 35fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * A class loader which loads classes from the dex file 36fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * "test.jar". However, it will return null when asked to load the 37fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * class InaccessibleSuper. 38fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 39fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * When testing code calls BrokenDexLoader's findBrokenClass(), 40fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * a BrokenDexLoader will be the defining loader for the class 41fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Inaccessible. The VM will call the defining loader for 42fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * "InaccessibleSuper", which will return null, which the VM 43fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * should be able to deal with gracefully. 44fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 45fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Note that this depends heavily on the Dalvik test harness. 46fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 47fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes static class BrokenDexLoader extends ClassLoader { 48fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 49fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** We return null when asked to load InaccessibleSuper. */ 50fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static class InaccessibleSuper {} 51fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static class Inaccessible extends InaccessibleSuper {} 52fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 53fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static final String SUPERCLASS_NAME = 54fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes "Main$BrokenDexLoader$InaccessibleSuper"; 55fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static final String CLASS_NAME = 56fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes "Main$BrokenDexLoader$Inaccessible"; 57fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 58fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static final String DEX_FILE = "test.jar"; 59fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 60fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes public BrokenDexLoader(ClassLoader parent) { 61fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes super(parent); 62fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 63fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 64fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 65fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Finds the class with the specified binary name, from DEX_FILE. 66fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 67fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * If we don't find a match, we throw an exception. 68fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 6982b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes private Class<?> findDexClass(String name) 7082b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes throws TestFailed, InvocationTargetException 71fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes { 72fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 73fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes try { 7482b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes /* 7582b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * Find the DexFile class, and construct a DexFile object 7682b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * through reflection, then call loadCLass on it. 7782b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes */ 7882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes Class mDexClass = ClassLoader.getSystemClassLoader(). 79a5a184892e60a89b564ca7c74e50b2ecb27d9f80Andy McFadden loadClass("dalvik.system.DexFile"); 8082b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes Constructor ctor = mDexClass. 8182b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes getConstructor(new Class[] {String.class}); 8282b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes Object mDexFile = ctor.newInstance(DEX_FILE); 8382b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes Method meth = mDexClass. 8482b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes getMethod("loadClass", 8582b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes new Class[] { String.class, ClassLoader.class }); 8682b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes /* 8782b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * Invoking loadClass on CLASS_NAME is expected to 8882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * throw an InvocationTargetException. Anything else 8982b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * is an error we can't recover from. 9082b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes */ 9182b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes meth.invoke(mDexFile, name, this); 92fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (NoSuchMethodException nsme) { 9382b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes throw new TestFailed(nsme); 94fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (InstantiationException ie) { 9582b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes throw new TestFailed(ie); 96fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (IllegalAccessException iae) { 9782b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes throw new TestFailed(iae); 9882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes } catch (ClassNotFoundException cnfe) { 9982b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes throw new TestFailed(cnfe); 100fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 101fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 102fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes return null; 103fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 104fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 105fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 106fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Load a class. 107fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 108fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Return null if the class's name is SUPERCLASS_NAME; 109fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * otherwise invoke the super's loadClass method. 110fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 111fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes public Class<?> loadClass(String name, boolean resolve) 112fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throws ClassNotFoundException 113fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes { 114fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes if (SUPERCLASS_NAME.equals(name)) { 115fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes return null; 116fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 117fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 118fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes return super.loadClass(name, resolve); 119fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 120fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 121fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 122fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Attempt to find the class with the superclass we refuse to 12382b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * load. This is expected to throw an 12482b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * InvocationTargetException, with a NullPointerException as 12582b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * its cause. 126fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 12782b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes public void findBrokenClass() 12882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes throws TestFailed, InvocationTargetException 129fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes { 130fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes findDexClass(CLASS_NAME); 131fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 132fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 133fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 134fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 135fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Main entry point. 136fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 13782b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes public static void main(String[] args) 13882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes throws TestFailed, ClassNotFoundException { 139fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /* 14082b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * Run test. 141fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 14282b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes testFailLoadAndGc(); 143fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 144fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 145fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 14682b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes * See if we can GC after a failed load. 147fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 14882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes static void testFailLoadAndGc() throws TestFailed { 149fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes try { 150fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes BrokenDexLoader loader; 151fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 152fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes loader = new BrokenDexLoader(ClassLoader.getSystemClassLoader()); 153fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes loader.findBrokenClass(); 154fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes System.err.println("ERROR: Inaccessible was accessible"); 15582b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes } catch (InvocationTargetException ite) { 15682b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes Throwable cause = ite.getCause(); 157fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes if (cause instanceof NullPointerException) { 15882b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes System.err.println("Got expected ITE/NPE"); 159fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } else { 16082b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes System.err.println("Got unexpected ITE"); 16182b596d087f29cd6b22f36dae28f1d25125e82c8Barry Hayes ite.printStackTrace(); 162fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 163fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 164fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 165fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes} 166