1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage dalvik.system; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.File; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.URL; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.zip.ZipFile; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.MalformedURLException; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport dalvik.system.DexFile; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Provides a simple {@link ClassLoader} implementation that operates on a 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list of jar/apk files with classes.dex entries. The directory that 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * holds the optimized form of the files is specified explicitly. This 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can be used to execute code not installed as part of an application. 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The best place to put the optimized DEX files is in app-specific 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * storage, so that removal of the app will automatically remove the 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * optimized DEX files. If other storage is used (e.g. /sdcard), the 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * app may not have an opportunity to remove them. 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DexClassLoader extends ClassLoader { 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final boolean VERBOSE_DEBUG = false; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* constructor args, held for init */ 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final String mRawDexPath; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final String mRawLibPath; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final String mDexOutputPath; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean mInitialized; 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parallel arrays for jar/apk files. 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (could stuff these into an object and have a single array; 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * improves clarity but adds overhead) 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private File[] mFiles; // source file Files, for rsrc URLs 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private ZipFile[] mZips; // source zip files, with resources 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private DexFile[] mDexs; // opened, prepped DEX files 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Native library path. 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private String[] mLibPaths; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Creates a {@code DexClassLoader} that finds interpreted and native 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * code. Interpreted classes are found in a set of DEX files contained 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in Jar or APK files. 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The path lists are separated using the character specified by 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the "path.separator" system property, which defaults to ":". 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param dexPath 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the list of jar/apk files containing classes and resources 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param dexOutputDir 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directory where optimized DEX files should be written 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param libPath 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the list of directories containing native libraries; may be null 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param parent 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the parent class loader 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public DexClassLoader(String dexPath, String dexOutputDir, String libPath, 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassLoader parent) { 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(parent); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dexPath == null || dexOutputDir == null) 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException(); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mRawDexPath = dexPath; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mDexOutputPath = dexOutputDir; 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mRawLibPath = libPath; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Complete initialization on first use of the class loader. 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private synchronized void ensureInit() { 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mInitialized) { 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String[] dexPathList; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mInitialized = true; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexPathList = mRawDexPath.split(":"); 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int length = dexPathList.length; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //System.out.println("DexClassLoader: " + dexPathList); 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mFiles = new File[length]; 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mZips = new ZipFile[length]; 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mDexs = new DexFile[length]; 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* open all Zip and DEX files up front */ 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < length; i++) { 11744b801d9b1dbe13aa441f16443aff8f19ee56e1cElliott Hughes //System.out.println("My path is: " + dexPathList[i]); 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project File pathFile = new File(dexPathList[i]); 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mFiles[i] = pathFile; 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pathFile.isFile()) { 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mZips[i] = new ZipFile(pathFile); 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IOException ioex) { 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // expecting IOException and ZipException 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("Failed opening '" + pathFile 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + "': " + ioex); 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //ioex.printStackTrace(); 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* we need both DEX and Zip, because dex has no resources */ 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String outputName = 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project generateOutputName(dexPathList[i], mDexOutputPath); 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mDexs[i] = DexFile.loadDex(dexPathList[i], outputName, 0); 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IOException ioex) { 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // might be a resource-only zip 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("Failed loadDex '" + pathFile 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + "': " + ioex); 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("Not found: " + pathFile.getPath()); 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Prep for native library loading. 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String pathList = System.getProperty("java.library.path", "."); 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String pathSep = System.getProperty("path.separator", ":"); 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String fileSep = System.getProperty("file.separator", "/"); 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mRawLibPath != null) { 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pathList.length() > 0) { 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pathList += pathSep + mRawLibPath; 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else { 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pathList = mRawLibPath; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mLibPaths = pathList.split(pathSep); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project length = mLibPaths.length; 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Add a '/' to the end so we don't have to do the property lookup 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // and concatenation later. 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < length; i++) { 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!mLibPaths[i].endsWith(fileSep)) 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mLibPaths[i] += fileSep; 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("Native lib path " +i+ ": " + mLibPaths[i]); 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert a source path name and an output directory to an output 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * file name. 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static String generateOutputName(String sourcePathName, 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String outputDir) { 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuilder newStr = new StringBuilder(80); 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* start with the output directory */ 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStr.append(outputDir); 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!outputDir.endsWith("/")) 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStr.append("/"); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* get the filename component of the path */ 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String sourceFileName; 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lastSlash = sourcePathName.lastIndexOf("/"); 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lastSlash < 0) 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceFileName = sourcePathName; 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceFileName = sourcePathName.substring(lastSlash+1); 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Replace ".jar", ".zip", whatever with ".dex". We don't want to 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * use ".odex", because the build system uses that for files that 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * are paired with resource-only jar files. If the VM can assume 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that there's no classes.dex in the matching jar, it doesn't need 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to open the jar to check for updated dependencies, providing a 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * slight performance boost at startup. The use of ".dex" here 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * matches the use on files in /data/dalvik-cache. 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lastDot = sourceFileName.lastIndexOf("."); 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lastDot < 0) 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStr.append(sourceFileName); 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStr.append(sourceFileName, 0, lastDot); 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStr.append(".dex"); 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("Output file will be " + newStr.toString()); 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return newStr.toString(); 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Finds a class. This method is called by {@code loadClass()} after the 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * parent ClassLoader has failed to find a loaded class of the same name. 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param name 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The name of the class to search for, in a human-readable form 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * like "java.lang.String" or "java.net.URLClassLoader$3$1". 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the {@link Class} object representing the class 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws ClassNotFoundException 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if the class cannot be found 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected Class<?> findClass(String name) throws ClassNotFoundException { 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureInit(); 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("DexClassLoader " + this 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + ": findClass '" + name + "'"); 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] data = null; 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int length = mFiles.length; 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < length; i++) { 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println(" Now searching: " + mFiles[i].getPath()); 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mDexs[i] != null) { 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String slashName = name.replace('.', '/'); 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Class clazz = mDexs[i].loadClass(slashName, this); 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz != null) { 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println(" found"); 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return clazz; 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ClassNotFoundException(name + " in loader " + this); 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Finds a resource. This method is called by {@code getResource()} after 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the parent ClassLoader has failed to find a loaded resource of the same 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * name. 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param name 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The name of the resource to find 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the location of the resource as a URL, or {@code null} if the 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resource is not found. 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected URL findResource(String name) { 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureInit(); 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int length = mFiles.length; 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < length; i++) { 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project File pathFile = mFiles[i]; 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ZipFile zip = mZips[i]; 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (zip.getEntry(name) != null) { 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println(" found " + name + " in " + pathFile); 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // File.toURL() is compliant with RFC 1738 in always 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // creating absolute path names. If we construct the 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // URL by concatenating strings, we might end up with 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // illegal URLs for relative names. 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return new URL("jar:" + pathFile.toURL() + "!/" + name); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (MalformedURLException e) { 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException(e); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println(" resource " + name + " not found"); 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Finds a native library. This method is called after the parent 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ClassLoader has failed to find a native library of the same name. 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param libname 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The name of the library to find 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the complete path of the library, or {@code null} if the library 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is not found. 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected String findLibrary(String libname) { 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ensureInit(); 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String fileName = System.mapLibraryName(libname); 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < mLibPaths.length; i++) { 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String pathName = mLibPaths[i] + fileName; 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project File test = new File(pathName); 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (test.exists()) { 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println(" found " + libname); 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pathName; 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (VERBOSE_DEBUG) 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println(" library " + libname + " not found"); 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns package information for the given package. Unfortunately, the 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * DexClassLoader doesn't really have this information, and as a non-secure 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ClassLoader, it isn't even required to, according to the spec. Yet, we 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to provide it, in order to make all those hopeful callers of 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <code>myClass.getPackage().getName()</code> happy. Thus we construct a 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Package object the first time it is being requested and fill most of the 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fields with dummy values. The Package object is then put into the 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ClassLoader's Package cache, so we see the same one next time. We don't 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * create Package objects for null arguments or for the default package. 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There a limited chance that we end up with multiple Package objects 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * representing the same package: It can happen when when a package is 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * scattered across different JAR files being loaded by different 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ClassLoaders. Rather unlikely, and given that this whole thing is more or 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * less a workaround, probably not worth the effort. 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param name 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the name of the class 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the package information for the class, or {@code null} if there 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is not package information available for it 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected Package getPackage(String name) { 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (name != null && !"".equals(name)) { 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project synchronized(this) { 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Package pack = super.getPackage(name); 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pack == null) { 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pack = definePackage(name, "Unknown", "0.0", "Unknown", 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "Unknown", "0.0", "Unknown", null); 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pack; 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 371