15d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/* 25d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Copyright (C) 2010 The Android Open Source Project 35d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 45d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Licensed under the Apache License, Version 2.0 (the "License"); 55d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * you may not use this file except in compliance with the License. 65d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * You may obtain a copy of the License at 75d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 85d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * http://www.apache.org/licenses/LICENSE-2.0 95d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Unless required by applicable law or agreed to in writing, software 115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * distributed under the License is distributed on an "AS IS" BASIS, 125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * See the License for the specific language governing permissions and 145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * limitations under the License. 155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.Constructor; 185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.Method; 195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.InvocationTargetException; 205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/** 225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Class loader test. 235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaopublic class Main { 255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Thrown when an unexpected Exception is caught internally. 275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao static class TestFailed extends Exception { 295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public TestFailed(Throwable cause) { 305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao super(cause); 315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * A class loader which loads classes from the dex file 365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * "test.jar". However, it will return null when asked to load the 375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * class InaccessibleSuper. 385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * When testing code calls BrokenDexLoader's findBrokenClass(), 405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * a BrokenDexLoader will be the defining loader for the class 415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Inaccessible. The VM will call the defining loader for 425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * "InaccessibleSuper", which will return null, which the VM 435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * should be able to deal with gracefully. 445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Note that this depends heavily on the Dalvik test harness. 465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao static class BrokenDexLoader extends ClassLoader { 485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** We return null when asked to load InaccessibleSuper. */ 505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static class InaccessibleSuper {} 515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static class Inaccessible extends InaccessibleSuper {} 525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static final String SUPERCLASS_NAME = 545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao "Main$BrokenDexLoader$InaccessibleSuper"; 555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private static final String CLASS_NAME = 565d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao "Main$BrokenDexLoader$Inaccessible"; 575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 586ce558b97f80d4ef7be2ef43333101d1aac7dcbfTDYa private static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/087-gc-after-link.jar"; 595d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 605d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public BrokenDexLoader(ClassLoader parent) { 615d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao super(parent); 625d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 635d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 645d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Finds the class with the specified binary name, from DEX_FILE. 665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * If we don't find a match, we throw an exception. 685d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 695d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private Class<?> findDexClass(String name) 705d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throws TestFailed, InvocationTargetException 715d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao { 725d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Object dexFile = null; 735d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Class dexClass = null; 745d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 755d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 765d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 775d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 785d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Find the DexFile class, and construct a DexFile object 795d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * through reflection, then call loadClass on it. 805d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 815d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao dexClass = ClassLoader.getSystemClassLoader(). 82741b5b7ef4c7fd4a786364bbf60d515489caff47Elliott Hughes loadClass("dalvik.system.DexFile"); 835d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Constructor ctor = dexClass. 845d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao getConstructor(new Class[] {String.class}); 855d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao dexFile = ctor.newInstance(DEX_FILE); 865d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Method meth = dexClass.getMethod("loadClass", 875d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao new Class[] { String.class, ClassLoader.class }); 885d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 895d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Invoking loadClass on CLASS_NAME is expected to 905d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * throw an InvocationTargetException. Anything else 915d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * is an error we can't recover from. 925d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 935d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao meth.invoke(dexFile, name, this); 9400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier System.out.println("Unreachable"); 955d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } finally { 965d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (dexFile != null) { 975d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* close the DexFile to make CloseGuard happy */ 985d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Method meth = dexClass.getMethod("close", (Class[]) null); 995d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao meth.invoke(dexFile); 1005d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1015d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1025d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (NoSuchMethodException nsme) { 1035d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new TestFailed(nsme); 1045d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (InstantiationException ie) { 1055d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new TestFailed(ie); 1065d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (IllegalAccessException iae) { 1075d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new TestFailed(iae); 1085d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (ClassNotFoundException cnfe) { 1095d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new TestFailed(cnfe); 1105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return null; 1135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 1165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Load a class. 1175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 1185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Return null if the class's name is SUPERCLASS_NAME; 1195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * otherwise invoke the super's loadClass method. 1205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public Class<?> loadClass(String name, boolean resolve) 1225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throws ClassNotFoundException 1235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao { 1245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (SUPERCLASS_NAME.equals(name)) { 1255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return null; 1265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return super.loadClass(name, resolve); 1295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 1325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Attempt to find the class with the superclass we refuse to 1335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * load. This is expected to throw an 1345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * InvocationTargetException, with a NullPointerException as 1355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * its cause. 1365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public void findBrokenClass() 1385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throws TestFailed, InvocationTargetException 1395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao { 1405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao findDexClass(CLASS_NAME); 1415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 1455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Main entry point. 1465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public static void main(String[] args) 1485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throws TestFailed, ClassNotFoundException { 1495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 1505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Run test. 1515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao testFailLoadAndGc(); 1535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 1565d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * See if we can GC after a failed load. 1575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1585d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao static void testFailLoadAndGc() throws TestFailed { 159831b1cc088ee21dfd0495fcce139d482b7380f6fMathieu Chartier processFailLoadAndGc(); 160831b1cc088ee21dfd0495fcce139d482b7380f6fMathieu Chartier Runtime.getRuntime().gc(); 161831b1cc088ee21dfd0495fcce139d482b7380f6fMathieu Chartier System.out.println("GC complete."); 162831b1cc088ee21dfd0495fcce139d482b7380f6fMathieu Chartier } 163831b1cc088ee21dfd0495fcce139d482b7380f6fMathieu Chartier 164831b1cc088ee21dfd0495fcce139d482b7380f6fMathieu Chartier private static void processFailLoadAndGc() throws TestFailed { 1655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao BrokenDexLoader loader; 1675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1685d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao loader = new BrokenDexLoader(ClassLoader.getSystemClassLoader()); 1695d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao loader.findBrokenClass(); 1705d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.err.println("ERROR: Inaccessible was accessible"); 1715d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (InvocationTargetException ite) { 1725d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Throwable cause = ite.getCause(); 1735d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (cause instanceof NullPointerException) { 1745d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.err.println("Got expected ITE/NPE"); 1755d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } else { 1765d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.err.println("Got unexpected ITE"); 1775d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao ite.printStackTrace(); 1785d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1795d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1805d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1815d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao} 182