15d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/* 25d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Copyright (C) 2008 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.io.File; 185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.io.FileNotFoundException; 195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.io.IOException; 205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.io.RandomAccessFile; 215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.Constructor; 225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.Method; 235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaoimport java.lang.reflect.InvocationTargetException; 245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao/** 265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * A class loader with atypical behavior: we try to load a private 275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * class implementation before asking the system or boot loader. This 285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * is used to create multiple classes with identical names in a single VM. 295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * If DexFile is available, we use that; if not, we assume we're not in 315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Dalvik and instantiate the class with defineClass(). 325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * The location of the DEX files and class data is dependent upon the 345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * test framework. 355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhaopublic class FancyLoader extends ClassLoader { 375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* this is where the "alternate" .class files live */ 384d9716c19cc25911e639272048abd0d6702bb082Brian Carlstrom static final String CLASS_PATH = "classes-ex/"; 395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* this is the "alternate" DEX/Jar file */ 411ed1a1320c89a143a8139d331a05d47ed3db64f7Mathieu Chartier static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/068-classloader-ex.jar"; 425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* on Dalvik, this is a DexFile; otherwise, it's null */ 445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private Class mDexClass; 455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private Object mDexFile; 475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Construct FancyLoader, grabbing a reference to the DexFile class 505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * if we're running under Dalvik. 515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao public FancyLoader(ClassLoader parent) { 535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao super(parent); 545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 56741b5b7ef4c7fd4a786364bbf60d515489caff47Elliott Hughes mDexClass = parent.loadClass("dalvik.system.DexFile"); 575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (ClassNotFoundException cnfe) { 585d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao // ignore -- not running Dalvik 595d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 605d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 615d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 625d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 635d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Finds the class with the specified binary name. 645d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * We search for a file in CLASS_PATH or pull an entry from DEX_FILE. 665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * If we don't find a match, we throw an exception. 675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 685d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao protected Class<?> findClass(String name) throws ClassNotFoundException 695d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao { 705d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (mDexClass != null) { 715d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return findClassDalvik(name); 725d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } else { 735d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return findClassNonDalvik(name); 745d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 755d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 765d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 775d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 785d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Finds the class with the specified binary name, from a DEX file. 795d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 805d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private Class<?> findClassDalvik(String name) 815d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throws ClassNotFoundException { 825d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 835d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (mDexFile == null) { 845d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao synchronized (FancyLoader.class) { 855d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Constructor ctor; 865d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 875d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Construct a DexFile object through reflection. 885d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 895d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 905d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao ctor = mDexClass.getConstructor(new Class[] {String.class}); 915d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (NoSuchMethodException nsme) { 925d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("getConstructor failed", 935d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao nsme); 945d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 955d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 965d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 974d9716c19cc25911e639272048abd0d6702bb082Brian Carlstrom mDexFile = ctor.newInstance(DEX_FILE); 985d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (InstantiationException ie) { 995d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("newInstance failed", ie); 1005d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (IllegalAccessException iae) { 1015d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("newInstance failed", iae); 1025d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (InvocationTargetException ite) { 1035d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("newInstance failed", ite); 1045d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1055d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1065d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1075d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1085d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 1095d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Call DexFile.loadClass(String, ClassLoader). 1105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Method meth; 1125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao meth = mDexClass.getMethod("loadClass", 1155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao new Class[] { String.class, ClassLoader.class }); 1165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (NoSuchMethodException nsme) { 1175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("getMethod failed", nsme); 1185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao meth.invoke(mDexFile, name, this); 1225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (IllegalAccessException iae) { 1235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("loadClass failed", iae); 1245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (InvocationTargetException ite) { 1255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("loadClass failed", 1265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao ite.getCause()); 1275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1295d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return null; 1305d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1315d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1325d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 1335d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Finds the class with the specified binary name, from .class files. 1345d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1355d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao private Class<?> findClassNonDalvik(String name) 1365d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throws ClassNotFoundException { 1375d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1385d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao String pathName = CLASS_PATH + name + ".class"; 1395d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao //System.out.println("--- Fancy: looking for " + pathName); 1405d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1415d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao File path = new File(pathName); 1425d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao RandomAccessFile raf; 1435d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1445d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1455d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao raf = new RandomAccessFile(path, "r"); 1465d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (FileNotFoundException fnfe) { 1475d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("Not found: " + pathName); 1485d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1495d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1505d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* read the entire file in */ 1515d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao byte[] fileData; 1525d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1535d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao fileData = new byte[(int) raf.length()]; 1545d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao raf.readFully(fileData); 1555d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (IOException ioe) { 1565d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("Read error: " + pathName); 1575d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } finally { 1585d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1595d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao raf.close(); 1605d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (IOException ioe) { 1615d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao // drop 1625d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1635d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1645d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1655d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* create the class */ 1665d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao //System.out.println("--- Fancy: defining " + name); 1675d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 1685d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return defineClass(name, fileData, 0, fileData.length); 1695d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } catch (Throwable th) { 1705d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throw new ClassNotFoundException("defineClass failed", th); 1715d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1725d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 1735d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1745d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /** 1755d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Load a class. 1765d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 1775d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * Normally a class loader wouldn't override this, but we want our 1785d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * version of the class to take precedence over an already-loaded 1795d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * version. 1805d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 1815d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * We still want the system classes (e.g. java.lang.Object) from the 1825d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * bootstrap class loader. 1835d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1845d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao protected Class<?> loadClass(String name, boolean resolve) 1855d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao throws ClassNotFoundException 1865d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao { 1875d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao Class res; 1885d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 1895d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 1905d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 1. Invoke findLoadedClass(String) to check if the class has 1915d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * already been loaded. 1925d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 1935d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * This doesn't change. 1945d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 1955d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao res = findLoadedClass(name); 1965d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (res != null) { 1975d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao System.out.println("FancyLoader.loadClass: " 1985d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao + name + " already loaded"); 1995d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (resolve) 2005d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao resolveClass(res); 2015d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return res; 2025d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 2035d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 2045d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 2055d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 3. Invoke the findClass(String) method to find the class. 2065d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 2075d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao try { 2085d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao res = findClass(name); 2095d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao if (resolve) 2105d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao resolveClass(res); 2115d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 2125d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao catch (ClassNotFoundException e) { 2135d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao // we couldn't find it, so eat the exception and keep going 2145d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 2155d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao 2165d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao /* 2175d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 2. Invoke the loadClass method on the parent class loader. If 2185d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * the parent loader is null the class loader built-in to the 2195d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * virtual machine is used, instead. 2205d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * 2215d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * (Since we're not in java.lang, we can't actually invoke the 2225d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * parent's loadClass() method, but we passed our parent to the 2235d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao * super-class which can take care of it for us.) 2245d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao */ 2255d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao res = super.loadClass(name, resolve); // returns class or throws 2265d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao return res; 2275d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao } 2285d1ac920fdaef5d4ec8f66bb734488cd9660b024jeffhao} 229