0x01 Lifetime of the loaded class

The problem mentioned yesterday is that there are at least two instances of ClassLoader in an App. One is the Boot type created when the system is started, and the other is fork out of the App. And if a class has been loaded, it will never be reloaded. What is this “forever” deadline? We can look at the implementation of ClassLoader. ClassLoader is an Abstract type, and we will use its subclasses DexClassLoader and PathClassLoader to implement class loading. The difference between DexClassLoader and PathClassLoader is as follows:

  • DexClassLoader can load JAR/APK /dex and load uninstalled APK from SD card.
  • The PathClassLoader can only load apK that has been installed in the system.
// DexClassLoader.java public class DexClassLoader extends BaseDexClassLoader { public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent) { super(dexPath, new File(optimizedDirectory), libraryPath, parent); }}Copy the code

The construction parameters of DexClassLoader are dexPath, optimizedDirectory, libraryPath, and parent.

// PathClassLoader.java
public class PathClassLoader extends BaseDexClassLoader {
    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }
    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}
Copy the code

The PathClassLoader constructor only has dexPath and libraryPath, missing the optimizedDirectory (super passed null). This optimizedDirectory is the reason why the PathClassLoader “only loads apK that has already been installed on the system”.

Take a look at the implementation in their common BaseDexClassLoader parent:

public BaseDexClassLoader(String dexPath, File optimizedDirectory, String libraryPath, ClassLoader parent) {
        super(parent);
        this.originalPath = dexPath;
        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
    }
Copy the code

Create a dexPath after the system automatically loadClass, and a DexPathList object. In dexPathlist.java there is a method like this:

private static DexFile loadDexFile(File file, File optimizedDirectory)
        throws IOException {
    if (optimizedDirectory == null) {
        return new DexFile(file);
    } else {
        String optimizedPath = optimizedPathFor(file, optimizedDirectory);
        returnDexFile.loadDex(file.getPath(), optimizedPath, 0); }}Copy the code

And:

/**
 * Converts a dex/jar file path and an output directory to an
 * output file path forAn associated Optimized dexfile. * Convert the dex/jar file path and output directory to an Output file path */ private static String optimizedPathFor(File path, File optimizedDirectory) { String fileName = path.getName();if(! fileName.endsWith(DEX_SUFFIX)) { int lastDot = fileName.lastIndexOf(".");
        if (lastDot < 0) {
            fileName += DEX_SUFFIX;
        } else {
            StringBuilder sb = new StringBuilder(lastDot + 4);
            sb.append(fileName, 0, lastDot);
            sb.append(DEX_SUFFIX);
            fileName = sb.toString();
        }
    }
    File result = new File(optimizedDirectory, fileName);
    return result.getPath();
}
Copy the code

OptimizedDirectory is used to store the dex files loaded. For example, if you want to load the DEX on the SD card, fill in the corresponding file path.

return DexFile.loadDex(file.getPath(), optimizedPath, 0);
Copy the code

A file is created to save (file.getPath()) in the application, so the “life” of the saved class after loading is before the application clears the cache or uninstalls the application.

As we learned earlier, classes that have been loaded by their parents will not be reloaded. This way, if you want to update a class dynamically, such as using the update plugin APk for “hot fixes,” you must use a different class, or the ClassLoader will use the loaded class. So when we use a new plug-in, we need to construct a new classLoader to load the dex of the plug-in. Alternatively, you might want to clear the cache path of the previously loaded dex.

We’re running out of time. We’ll talk tomorrow.

-NOV22