DexPathList的构造

/**
     * Constructs an instance.
     *
     * dexFile must be an in-memory representation of a full dexFile.
     *
     * @param dexFiles the array of in-memory dex files containing classes.
     * @param parent the parent class loader
     *
     * @hide
     */
    public BaseDexClassLoader(ByteBuffer[] dexFiles, ClassLoader parent) {
        // TODO We should support giving this a library search path maybe.
        super(parent);
        this.pathList = new DexPathList(this, dexFiles);
    }
DexPathList(ClassLoader definingContext, String dexPath,
            String librarySearchPath, File optimizedDirectory, boolean isTrusted) {
            ...
             this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,suppressedExceptions, definingContext, isTrusted);
            ...
            }
private private static Element[] makeDexElements(List files, File optimizedDirectory,
           List suppressedExceptions, ClassLoader loader, boolean isTrusted) {
     Element[] elements = new Element[files.size()];
     int elementsPos = 0;
     /*
      * Open all files and load the (direct or contained) dex files up front.
      */
     for (File file : files) {
         if (file.isDirectory()) {
             // We support directories for looking up resources. Looking up resources in
             // directories is useful for running libcore tests.
             elements[elementsPos++] = new Element(file);
         } else if (file.isFile()) {
             String name = file.getName();

             DexFile dex = null;
             if (name.endsWith(DEX_SUFFIX)) {
                 // Raw dex file (not inside a zip/jar).
                 try {
                     dex = loadDexFile(file, optimizedDirectory, loader, elements);
                     if (dex != null) {
                         elements[elementsPos++] = new Element(dex, null);
                     }
                 } catch (IOException suppressed) {
                     System.logE("Unable to load dex file: " + file, suppressed);
                     suppressedExceptions.add(suppressed);
                 }
             } else {
                 try {
                     dex = loadDexFile(file, optimizedDirectory, loader, elements);
                 } catch (IOException suppressed) {
                     /*
                      * IOException might get thrown "legitimately" by the DexFile constructor if
                      * the zip file turns out to be resource-only (that is, no classes.dex file
                      * in it).
                      * Let dex == null and hang on to the exception to add to the tea-leaves for
                      * when findClass returns null.
                      */
                     suppressedExceptions.add(suppressed);
                 }

                 if (dex == null) {
                     elements[elementsPos++] = new Element(file);
                 } else {
                     elements[elementsPos++] = new Element(dex, file);
                 }
             }
             if (dex != null && isTrusted) {
               dex.setTrusted();
             }
         } else {
             System.logW("ClassLoader referenced unknown path: " + file);
         }
     }
     if (elementsPos != elements.length) {
         elements = Arrays.copyOf(elements, elementsPos);
     }
     return elements;
   }
/**
     * Constructs a {@code DexFile} instance, as appropriate depending on whether
     * {@code optimizedDirectory} is {@code null}. An application image file may be associated with
     * the {@code loader} if it is not null.
     */
    private static DexFile loadDexFile(File file, File optimizedDirectory, ClassLoader loader,
                                       Element[] elements)
            throws IOException {
        if (optimizedDirectory == null) {
            return new DexFile(file, loader, elements);
        } else {
            String optimizedPath = optimizedPathFor(file, optimizedDirectory);
            return DexFile.loadDex(file.getPath(), optimizedPath, 0, loader, elements);
        }
    }
/**
 * Representation of an entire {@code .dex} (Dalvik EXecutable)
 * file, which itself consists of a set of Dalvik classes.
 */
public final class DexFile {

}

DexPathlist借助DexFile的native方法完成.dex文件的加载

一个Element对应一个DexFile.

热修复怎么实现?

类加载器加载类其实是在dexElements中加载,将新的.dex插入到dexElements的数组起始位置。

为什么是前面?

前面找到了就不会往后面找同一个类。

热修复流派:

native:阿里

java:

​ mutidex: tinker(classloader修改elements) qzone超级补丁

​ instant-run(美团):可以即时生效,不需要重启,重启是因为补丁加载是在Applicatiion类的启动过程中调用

tinker是怎么写的?

github上 systemclassloaderAdder类 installDex中

原理:修改Dexpathlist中的dexElements数组中.

1.classloader拿到baseClassloder中的dexPathlist
2.找dexElements,修改它  找到新的把新的插入到它的前面

讲工程代码:第二节: 【15:38】

instant run模式讲解[30:00]

增量更新。

兼容的作业【45分】


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!