This is the 11th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

preface

The first stage in the Class lifecycle is the Class loading stage, where the binary stream of non-array classes is loaded into memory and a Java.lang.class object is generated.

This article mainly discusses the story happened in this stage.


Class loaders

1.1 Class loader types

There are three important classloaders built into the JVM. With the exception of BootstrapClassLoader, all class loaders are implemented by Java and all inherit from Java.lang.ClassLoader

(Figure) Class loader hierarchy

For the JVM, there are two types of classloaders:

  1. Startup class loader: for the Hotsopt virtual machine, the startup class loader is implemented in C++ and is part of the virtual machine
  2. Other class loaders: These loaders are implemented in the Java language, are independent of the virtual machine, and are all inherited fromjava.lang.ClassLoaderThese class loaders need to be loaded into memory by the bootstrap class in order to load other classes

For developers, class loaders fall into three categories:

  1. Start the class loaderBootstrap ClassLoader: Is responsible for loading${JAVA_HOME}/jre/libDirectory, or by-XbootclasspathThe class library in the path specified by the parameter can be identified by the VM. The startup class loader is not available to developers.
  2. Extend the class loaderExtension ClassLoader: is mainly responsible for loading%JRE_HOME%/lib/extDirectory containing jar packages and classes, or byjava.ext.dirsJar package in the path specified by the system variable; Developers can use extension class loaders directly.
  3. Application ClassLoader: a loader for our users that is responsible for loading all jar packages and classes in the current Application classpath; Developers can use the class loader directly.


1.2 Querying the classloader of the class

Example code:

public class Test {
    public static void main(String[] args) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); System.out.println(classLoader); System.out.println(classLoader.getParent()); System.out.println(classLoader.getParent().getParent()); }}Copy the code

Output:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@4eec7777
null
Copy the code

The third reason for null is because the HotSopt BootstrapClassLoader is implemented in C++ and cannot find a concrete object


1.3 Custom class loaders

Most of the time, we use the system classloader directly, but there are some that require our own class loader. For example, the bytecode files that are transmitted over the network are encrypted so that the system loader cannot load the classes

All class loaders except BootstrapClassLoader are implemented in Java and all inherit from Java.lang.ClassLoader. If we want to customize our own ClassLoader, we just need to inherit from ClassLoader


Ii. Parent delegation mechanism

Each class has its own ClassLoader, and classloaders in the system use parent delegation by default when working together

Parent delegation mechanism:

  1. During class loading, the system first determines whether the current class has been loaded. Classes that have already been loaded are returned directly, otherwise loading is attempted.
  2. When loading, the request is first delegated to the parent class loaderloadClass()When the parent class loader is NULL, the bootstrap class loader is usedBootstrapClassLoaderAs the parent class loader, all requests go to the startup class loader.
  3. When the request arrivesBootstrapClassLoaderI’m going to check from top to bottom to see if it can be loaded until someone says yes.


2.1 Code implementation of the parent delegate mechanism

In the loadClass() of java.lang.classLoader


publicClass<? > loadClass(String name)throws ClassNotFoundException {
        return loadClass(name, false);
}
protected synchronizedClass<? > loadClass(String name,boolean resolve) throws ClassNotFoundException {
    // First check whether the type has been loaded
    Class c = findLoadedClass(name);
    if (c == null) {
        // If it is not loaded, delegate to the parent class loader or delegate to the bootstrap class loader
        try {
            if(parent ! =null) {
                // Delegate to the parent class loader, if it exists
                c = parent.loadClass(name, false);
            } else {
                // If there is no parent Class loader, check if the Class was loaded by the bootstrap Class loader by calling the local method native Class findBootstrapClass(String name)c = findBootstrapClass0(name); }}catch (ClassNotFoundException e) {
            // If neither the parent class loader nor the bootstrap class loader can complete the load task, the own load function is calledc = findClass(name); }}if (resolve) {
        resolveClass(c);
    }
    return c;
}
Copy the code


2.2 Why use parent delegation

The parent delegate mechanism prevents classes from being loaded repeatedly, especially the core classes of the system.

If someone wants to replace the system-level class java.lang.String now, it has already been loaded by the BootstrapClassLoader under the parent delegation mechanism, and no other classloader has a chance to load it.

Thus, the parent delegate model ensures that Java programs run stably and that Java’s core APIS are not tampered with.


3. To summarize

The JVM class loading mechanism is summarized as follows:

  1. Overall delegation: When a classloader is responsible for loading a Class, other classes that that Class depends on and references are also responsible for loading by that Class loader, unless it is shown to be loaded by another classloader
  2. Caching mechanism: The caching mechanism ensures that all classes loaded are cached. When a Class needs to be used in the program, the Class loader first looks for the Class from the cache before executing the loading logic and storing it in the cache
  3. Parent delegation: If a classloader receives a class loading request, it does not first attempt to load the class itself. Instead, it delegates the request to the parent, and so on. If the parent class loader cannot load, go down