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