12cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom/* 22cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Copyright (C) 2007 The Android Open Source Project 32cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 42cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 52cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * you may not use this file except in compliance with the License. 62cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * You may obtain a copy of the License at 72cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 82cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 92cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * See the License for the specific language governing permissions and 142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * limitations under the License. 152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrompackage dalvik.system; 182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.io.File; 202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.io.FileNotFoundException; 212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.io.IOException; 222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.ArrayList; 232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.Enumeration; 242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.List; 252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport libcore.io.ErrnoException; 262cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport libcore.io.Libcore; 272cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport libcore.io.StructStat; 282cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 292cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom/** 302cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Manipulates DEX files. The class is similar in principle to 312cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * {@link java.util.zip.ZipFile}. It is used primarily by class loaders. 322cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * <p> 332cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Note we don't directly open and read the DEX file here. They're memory-mapped 342cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * read-only by the VM. 352cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 362cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrompublic final class DexFile { 372cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private int mCookie; 382cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private final String mFileName; 392cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 402cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 412cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 422cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Opens a DEX file from a given File object. This will usually be a ZIP/JAR 432cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * file with a "classes.dex" inside. 442cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 452cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * The VM will generate the name of the corresponding file in 462cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * /data/dalvik-cache and open it, possibly creating or updating 472cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * it first if system permissions allow. Don't pass in the name of 482cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * a file in /data/dalvik-cache, as the named file is expected to be 492cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * in its original (pre-dexopt) state. 502cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 512cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param file 522cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * the File object referencing the actual DEX file 532cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 542cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws IOException 552cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * if an I/O error occurs, such as the file not being found or 562cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * access rights missing for opening it 572cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 582cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public DexFile(File file) throws IOException { 592cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom this(file.getPath()); 602cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 612cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 622cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 632cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Opens a DEX file from a given filename. This will usually be a ZIP/JAR 642cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * file with a "classes.dex" inside. 652cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 662cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * The VM will generate the name of the corresponding file in 672cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * /data/dalvik-cache and open it, possibly creating or updating 682cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * it first if system permissions allow. Don't pass in the name of 692cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * a file in /data/dalvik-cache, as the named file is expected to be 702cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * in its original (pre-dexopt) state. 712cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 722cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param fileName 732cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * the filename of the DEX file 742cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 752cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws IOException 762cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * if an I/O error occurs, such as the file not being found or 772cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * access rights missing for opening it 782cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 792cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public DexFile(String fileName) throws IOException { 802cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom mCookie = openDexFile(fileName, null, 0); 812cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom mFileName = fileName; 822cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom guard.open("close"); 832cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom //System.out.println("DEX FILE cookie is " + mCookie); 842cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 852cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 862cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 872cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Opens a DEX file from a given filename, using a specified file 882cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * to hold the optimized data. 892cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 902cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param sourceName 912cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Jar or APK file with "classes.dex". 922cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param outputName 932cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * File that will hold the optimized form of the DEX data. 942cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param flags 952cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Enable optional features. 962cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 972cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private DexFile(String sourceName, String outputName, int flags) throws IOException { 982cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (outputName != null) { 992cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom try { 1002cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom String parent = new File(outputName).getParent(); 1012cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (Libcore.os.getuid() != Libcore.os.stat(parent).st_uid) { 1022cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom throw new IllegalArgumentException("Optimized data directory " + parent 1032cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom + " is not owned by the current user. Shared storage cannot protect" 1042cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom + " your application from code injection attacks."); 1052cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1062cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } catch (ErrnoException ignored) { 1072cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom // assume we'll fail with a more contextual error later 1082cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1092cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom mCookie = openDexFile(sourceName, outputName, flags); 1122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom mFileName = sourceName; 1132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom guard.open("close"); 1142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom //System.out.println("DEX FILE cookie is " + mCookie); 1152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 1182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Open a DEX file, specifying the file in which the optimized DEX 1192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * data should be written. If the optimized form exists and appears 1202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * to be current, it will be used; if not, the VM will attempt to 1212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * regenerate it. 1222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * This is intended for use by applications that wish to download 1242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * and execute DEX files outside the usual application installation 1252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * mechanism. This function should not be called directly by an 1262cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * application; instead, use a class loader such as 1272cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * dalvik.system.DexClassLoader. 1282cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1292cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param sourcePathName 1302cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Jar or APK file with "classes.dex". (May expand this to include 1312cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * "raw DEX" in the future.) 1322cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param outputPathName 1332cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * File that will hold the optimized form of the DEX data. 1342cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param flags 1352cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Enable optional features. (Currently none defined.) 1362cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @return 1372cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * A new or previously-opened DexFile. 1382cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws IOException 1392cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * If unable to open the source or output file. 1402cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 1412cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom static public DexFile loadDex(String sourcePathName, String outputPathName, 1422cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom int flags) throws IOException { 1432cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1442cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /* 1452cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * TODO: we may want to cache previously-opened DexFile objects. 1462cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * The cache would be synchronized with close(). This would help 1472cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * us avoid mapping the same DEX more than once when an app 1482cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * decided to open it multiple times. In practice this may not 1492cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * be a real issue. 1502cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 1512cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return new DexFile(sourcePathName, outputPathName, flags); 1522cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1532cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1542cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 1552cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Gets the name of the (already opened) DEX file. 1562cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1572cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @return the file name 1582cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 1592cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public String getName() { 1602cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return mFileName; 1612cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1622cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1632cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 1642cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Closes the DEX file. 1652cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * <p> 1662cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * This may not be able to release any resources. If classes from this 1672cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * DEX file are still resident, the DEX file can't be unmapped. 1682cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1692cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws IOException 1702cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * if an I/O error occurs during closing the file, which 1712cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * normally should not happen 1722cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 1732cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public void close() throws IOException { 1742cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (mCookie != 0) { 1752cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom guard.close(); 1762cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom closeDexFile(mCookie); 1772cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom mCookie = 0; 1782cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1792cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1802cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1812cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 1822cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Loads a class. Returns the class on success, or a {@code null} reference 1832cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * on failure. 1842cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * <p> 1852cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * If you are not calling this from a class loader, this is most likely not 1862cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * going to do what you want. Use {@link Class#forName(String)} instead. 1872cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * <p> 1882cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * The method does not throw {@link ClassNotFoundException} if the class 1892cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * isn't found because it isn't reasonable to throw exceptions wildly every 1902cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * time a class is not found in the first DEX file we look at. 1912cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1922cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param name 1932cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * the class name, which should look like "java/lang/String" 1942cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1952cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param loader 1962cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * the class loader that tries to load the class (in most cases 1972cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * the caller of the method 1982cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1992cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @return the {@link Class} object representing the class, or {@code null} 2002cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * if the class cannot be loaded 2012cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 2022cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public Class loadClass(String name, ClassLoader loader) { 2032cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom String slashName = name.replace('.', '/'); 2042cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return loadClassBinaryName(slashName, loader, null); 2052cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2062cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2072cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 2082cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * See {@link #loadClass(String, ClassLoader)}. 2092cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 2102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * This takes a "binary" class name to better match ClassLoader semantics. 2112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 2122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @hide 2132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 2142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) { 2152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return defineClass(name, loader, mCookie, suppressed); 2162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private static Class defineClass(String name, ClassLoader loader, int cookie, 2192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom List<Throwable> suppressed) { 2202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom Class result = null; 2212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom try { 2222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom result = defineClassNative(name, loader, cookie); 2232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } catch (NoClassDefFoundError e) { 2242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (suppressed != null) { 2252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom suppressed.add(e); 226ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom } 2272cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } catch (ClassNotFoundException e) { 2282cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (suppressed != null) { 2292cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom suppressed.add(e); 230ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom } 2312cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2322cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return result; 2332cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2342cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2352cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private static native Class defineClassNative(String name, ClassLoader loader, int cookie) 2362cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom throws ClassNotFoundException, NoClassDefFoundError; 2372cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2382cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 2392cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Enumerate the names of the classes in this DEX file. 2402cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 2412cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @return an enumeration of names of classes contained in the DEX file, in 2422cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * the usual internal form (like "java/lang/String"). 2432cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 2442cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public Enumeration<String> entries() { 2452cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return new DFEnum(this); 2462cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2472cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2482cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /* 2492cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Helper class. 2502cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 2512cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private class DFEnum implements Enumeration<String> { 2522cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private int mIndex; 2532cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private String[] mNameList; 2542cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2552cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom DFEnum(DexFile df) { 2562cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom mIndex = 0; 2572cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom mNameList = getClassNameList(mCookie); 2582cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2592cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2602cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public boolean hasMoreElements() { 2612cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return (mIndex < mNameList.length); 2622cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2632cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2642cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public String nextElement() { 2652cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return mNameList[mIndex++]; 2662cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2672cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2682cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2692cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /* return a String array with class names */ 2702cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom native private static String[] getClassNameList(int cookie); 2712cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2722cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 2732cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Called when the class is finalized. Makes sure the DEX file is closed. 2742cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 2752cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws IOException 2762cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * if an I/O error occurs during closing the file, which 2772cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * normally should not happen 2782cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 2792cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom @Override protected void finalize() throws Throwable { 2802cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom try { 2812cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (guard != null) { 2822cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom guard.warnIfOpen(); 2832cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2842cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom close(); 2852cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } finally { 2862cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom super.finalize(); 2872cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2882cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 2892cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 2902cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /* 2912cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Open a DEX file. The value returned is a magic VM cookie. On 2922cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * failure, an IOException is thrown. 2932cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 294ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom private static int openDexFile(String sourceName, String outputName, 295ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom int flags) throws IOException { 296ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom return openDexFileNative(new File(sourceName).getCanonicalPath(), 297ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom (outputName == null) ? null : new File(outputName).getCanonicalPath(), 298ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom flags); 299ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom } 300ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom 301ca2c58ceaf2d35d30fe06b1676cc1436a24c4d30Brian Carlstrom native private static int openDexFileNative(String sourceName, String outputName, 3022cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom int flags) throws IOException; 3032cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 3042cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /* 3052cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Close DEX file. 3062cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 3072cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom native private static void closeDexFile(int cookie); 3082cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 3092cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 3102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Returns true if the VM believes that the apk/jar file is out of date 3112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * and should be passed through "dexopt" again. 3122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 3132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param fileName the absolute path to the apk/jar file to examine. 3142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @return true if dexopt should be called on the file, false otherwise. 3152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws java.io.FileNotFoundException if fileName is not readable, 3162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * not a file, or not present. 3172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws java.io.IOException if fileName is not a valid apk/jar file or 3182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * if problems occur while parsing it. 3192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws java.lang.NullPointerException if fileName is null. 3202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @throws dalvik.system.StaleDexCacheError if the optimized dex file 3212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * is stale but exists on a read-only partition. 3222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 3232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom native public static boolean isDexOptNeeded(String fileName) 3242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom throws FileNotFoundException, IOException; 3252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom} 326