Traditional Jvm

The Java VIRTUAL machine loads the data describing the Class from the Class file to the memory, verifies, transforms, and initializes the data, and finally forms Java types that can be directly used by VMS. This is the Class loading mechanism of virtual machines.

Class life cycle

The entire life cycle of a class from when it is loaded into virtual machine memory to when it is unloaded from memory includes: 2, Loading, Verification, Preparation, Resolution, Initialization, Using and Unloading are two stages. Among them, validation, preparation and parsing are collectively referred to as Linking. The sequence of these 7 stages is shown in the figure

Class loader

For any class, the uniqueness of the Java virtual machine needs to be established both by the class loader that loads it and by the class itself. Each class loader has a separate class namespace. This sentence can express more popular: * * compare whether the two classes “equal”, only in these two classes are from the same Class loader under the premise of load to be meaningful, otherwise, even if these two classes derived from the same Class files, by the same virtual machine loading, as long as the load they’re different Class loaders, these two classes are not necessarily equal. 支那

Parental delegation model

Most Java programs use one of three system-provided classloaders:

  1. Bootstrap ClassLoader

This class handler is responsible for storing it in the < JAVA_HOME > \lib directory, or in the path specified by the -xbootCLASspath parameter, and is recognized by the virtual machine (only by filename, such as rt.jar, Libraries with incorrect names will not be loaded even if placed in the lib directory.) Libraries are loaded into the virtual machine memory. The boot class loader cannot be directly referenced by Java programs. If you need to delegate the loading request to the boot class loader when writing a custom class loader, you can use NULL instead.

  1. Extension ClassLoader

This loader is implemented by sun.misc.Launcher $ExtClassLoader, which loads all libraries in the < JAVA_HOME > \lib\ext directory, or in the path specified by the java.ext.dirs system variable. Developers can use the extended classloader directly.

  1. Application ClassLoader

The ClassLoader is implemented by sun.misc.Launcher $app-classloader. Since this ClassLoader is the return value of the getSystemClassLoader () method in ClassLoader, it is also commonly referred to as the system ClassLoader. It is responsible for loading the libraries specified on the user’s ClassPath. Developers can use this class loader directly, and this is generally the default class loader if the application does not have its own custom class loader.

Java applications are typically loaded by a combination of these three types of loaders and, if necessary, their own class loaders. The relationship between these classloaders is typically shown in the figure below.

This hierarchical relationship between class loaders, shown in the figure above, is called the Parents Delegation Model of class loaders. The parent delegate model requires that all class loaders have their own parent class loaders, except for the top-level start class loaders. The parent-child relationship between class loaders is not typically implemented in an Inheritance relationship, but in a Composition relationship that replicates the code of the parent loader.

The working process of the parental delegation model is: If a classloader receives a classload request, it does not try to load the class itself at first. Instead, it delegates the request to the parent classloader. This is true at every level of classloaders, so all load requests should eventually be passed to the top level of the starting classloader. Only when the parent loader reports that it cannot complete the load request (it did not find the desired class in its search scope) will the child loader attempt to load it itself.

Android ClassLoader mechanism

Essentially, Android is the same as a traditional JVM in that the target classes need to be loaded into memory by a ClassLoader. The classloaders also conform to the parent-delegate model, and the classes have corresponding life cycles. However, based on the characteristics of mobile devices, such as memory, power and many other aspects, which are essentially different from ordinary PC devices, Google developed virtual machines for executing Java codes that are more suitable for mobile devices, namely Dalvik and ART. Since 5.0, Android has used AR virtual machines to replace Dalvik. Traditional JVMS load primarily by reading class bytecode, whereas ART reads from dex bytecode. This is a more optimized solution, combining multiple. Class files into a single classes.dex file.

This diagram

BaseDexClassLoader

public class BaseDexClassLoader extends ClassLoader {
    private final DexPathList pathList;
    public BaseDexClassLoader(String dexPath, File optimizedDirectory, String librarySearchPath, ClassLoader parent) {
        super(parent);
        this.pathList = new DexPathList(this, dexPath, librarySearchPath, null);
    }
    @Override
    protectedClass<? > findClass(String name)throwsClassNotFoundException { ... . Class c = pathList.findClass(name, suppressedExceptions); . .return c;
    }
    @Override
    protected URL findResource(String name) {
        return pathList.findResource(name);
    }
    @Override
    public String findLibrary(String name) {
        returnpathList.findLibrary(name); }}Copy the code

You can see that the DexPathList object is initialized in the constructor, and the operations findClass and findResource in BaseDexClassLoader perform operations on the DexPathList object. The DexPathList is not expanded here.

As you can see from the DexPathList construction process, whatever the value of optimizedDirectory is passed is empty, so the optimizedDirectory argument is invalid (starting from Android8.0)

PathClassLoader

public class PathClassLoader extends BaseDexClassLoader {

    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null.null, parent);
    }

    public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
        super(dexPath, null, librarySearchPath, parent); }}Copy the code

PathClassLoader is relatively simple and inherits from BaseDexClassLoader. OptimizedDirectory = null by default.

DexClassLoader

public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {
        super(dexPath, null, librarySearchPath, parent); }}Copy the code

DexClassLoader is also relatively simple, just simple encapsulation, and PathClassLoader is the only difference is more optimizedDirectory parameter, but from the above BaseDexClassLoader analysis can know, As of 8.0 optimizedDirectory is deprecated. In theory, PathClassLoader should completely replace DexClassLoader. But here’s the verdict from the Internet:

DexClassLoader: loads the apK that is not installed

PathClassLoader: only apK that has been installed in the system can be loaded

In fact, PathClassLoader can also load uninstalled APK. The verification process is relatively simple, so you can try it yourself if you are interested.

reference

www.jianshu.com/p/78f9a3f55…