Main.java revision fbb80d7f726e551161fccbf0e347624459aefedf
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 { 25fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 26fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 27fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * A class loader which loads classes from the dex file 28fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * "test.jar". However, it will return null when asked to load the 29fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * class InaccessibleSuper. 30fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 31fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * When testing code calls BrokenDexLoader's findBrokenClass(), 32fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * a BrokenDexLoader will be the defining loader for the class 33fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Inaccessible. The VM will call the defining loader for 34fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * "InaccessibleSuper", which will return null, which the VM 35fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * should be able to deal with gracefully. 36fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 37fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Note that this depends heavily on the Dalvik test harness. 38fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 39fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes static class BrokenDexLoader extends ClassLoader { 40fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 41fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** We return null when asked to load InaccessibleSuper. */ 42fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static class InaccessibleSuper {} 43fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static class Inaccessible extends InaccessibleSuper {} 44fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 45fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static final String SUPERCLASS_NAME = 46fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes "Main$BrokenDexLoader$InaccessibleSuper"; 47fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static final String CLASS_NAME = 48fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes "Main$BrokenDexLoader$Inaccessible"; 49fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 50fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private static final String DEX_FILE = "test.jar"; 51fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 52fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes public BrokenDexLoader(ClassLoader parent) { 53fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes super(parent); 54fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 55fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 56fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 57fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Finds the class with the specified binary name, from DEX_FILE. 58fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 59fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * If we don't find a match, we throw an exception. 60fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 61fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes private Class<?> findDexClass(String name) throws ClassNotFoundException 62fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes { 63fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes Class mDexClass; 64fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes Object mDexFile; 65fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 66fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /* 67fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Find the DexFile class, and construct a DexFile object 68fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * through reflection. 69fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 70fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 71fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes mDexClass = ClassLoader.getSystemClassLoader(). 72fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes loadClass("dalvik/system/DexFile"); 73fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 74fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes Constructor ctor; 75fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes try { 76fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes ctor = mDexClass.getConstructor(new Class[] {String.class}); 77fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (NoSuchMethodException nsme) { 78fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throw new ClassNotFoundException("getConstructor failed", 79fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes nsme); 80fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 81fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 82fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes try { 83fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes mDexFile = ctor.newInstance(DEX_FILE); 84fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (InstantiationException ie) { 85fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throw new ClassNotFoundException("newInstance failed", ie); 86fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (IllegalAccessException iae) { 87fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throw new ClassNotFoundException("newInstance failed", iae); 88fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (InvocationTargetException ite) { 89fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throw new ClassNotFoundException("newInstance failed", ite); 90fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 91fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 92fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /* 93fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Call DexFile.loadClass(String, ClassLoader). 94fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 95fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes Method meth; 96fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 97fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes try { 98fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes meth = mDexClass.getMethod("loadClass", 99fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes new Class[] { String.class, ClassLoader.class }); 100fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (NoSuchMethodException nsme) { 101fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throw new ClassNotFoundException("getMethod failed", nsme); 102fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 103fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 104fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes try { 105fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes meth.invoke(mDexFile, name, this); 106fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (IllegalAccessException iae) { 107fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throw new ClassNotFoundException("loadClass failed", iae); 108fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (InvocationTargetException ite) { 109fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throw new ClassNotFoundException("loadClass failed", 110fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes ite.getCause()); 111fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 112fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 113fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes return null; 114fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 115fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 116fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 117fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Load a class. 118fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * 119fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Return null if the class's name is SUPERCLASS_NAME; 120fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * otherwise invoke the super's loadClass method. 121fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 122fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes public Class<?> loadClass(String name, boolean resolve) 123fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes throws ClassNotFoundException 124fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes { 125fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes if (SUPERCLASS_NAME.equals(name)) { 126fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes return null; 127fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 128fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 129fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes return super.loadClass(name, resolve); 130fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 131fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 132fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 133fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Attempt to find the class with the superclass we refuse to 134fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * load. 135fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 136fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes public void findBrokenClass() throws ClassNotFoundException 137fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes { 138fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes findDexClass(CLASS_NAME); 139fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 140fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 141fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 142fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 143fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Main entry point. 144fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 145fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes public static void main(String[] args) throws ClassNotFoundException { 146fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /* 147fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Run tests. 148fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 149fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes testAccess(); 150fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 151fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 152fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes /** 153fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * See if we can load a class when the loader returns null for the 154fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * superclass. 155fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */ 156fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes static void testAccess() { 157fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes try { 158fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes BrokenDexLoader loader; 159fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes 160fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes loader = new BrokenDexLoader(ClassLoader.getSystemClassLoader()); 161fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes loader.findBrokenClass(); 162fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes System.err.println("ERROR: Inaccessible was accessible"); 163fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } catch (ClassNotFoundException cnfe) { 164fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes Throwable cause = cnfe.getCause(); 165fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes if (cause instanceof NullPointerException) { 166fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes System.out.println("Got expected CNFE/NPE"); 167fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } else { 168fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes System.err.println("Got unexpected CNFE"); 169fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes cnfe.printStackTrace(); 170fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 171fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 172fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes } 173fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes} 174