Talk about Java class loading mechanism

Java interviews often ask what the Java class loading mechanism is. Today we will introduce the Java class loader and the class loading process. Let me talk about the class loading process.

Java interview questions often ask what the class loading process is, or by giving you a program and answering the output of the program. These knowledge points are related to the Java class loading process. Talk about the 7 processes of class loading.

Class loading process

load

Load the class file into memory and create the corresponding class object in the method area

verification

Check whether the loaded class file conforms to the bytecode specification

ready

  • After completing the verification phase, jvm starts allocating memory for class variables and initializing zero values.
  • "Class variables" refer to variables modified by static.
  • In the preparation stage, the JVM will only allocate memory for "class variables", not for "class member variables".
  • But if a variable is a constant (modified by static final), then in the preparation stage, the attribute will be given the user's desired value. Because the value modified by final cannot be changed once it is assigned.

Parsing

The JVM resolves 7 types of references to classes or interfaces, fields, class methods, interface methods, method types, method handles, and call point qualifiers. The main task of this stage is to replace its symbol reference in the constant pool with its direct reference in memory.

initialization

At the initialization stage, the user-defined Java program code really begins to execute. At this stage, the JVM will initialize the class objects according to the execution order of the statements. Generally speaking, when the JVM encounters the following 5 situations, it will trigger the initialization:

  • When encountering the four bytecode instructions new, getstatic, putstatic, invokestatic, if the class has not been initialized, you need to trigger its initialization first. The most common Java code scenario that generates these 4 instructions is: when using the new keyword to instantiate an object, read or set a static field of a class (decorated by final, the static that has been put into the constant pool by the compiler Except for fields), and when calling static methods of a class.
  • When using the methods of the java.lang.reflect package to make a reflective call to a class, if the class has not been initialized, you need to trigger its initialization first.
  • When initializing a class, if you find that its parent class has not been initialized, you need to trigger the initialization of its parent class first.
  • When the virtual machine starts, the user needs to specify a main class to be executed (the one containing the main () method), and the virtual machine first initializes this main class.
  • When using JDK1.7 dynamic language support, if the final analysis result of a java.lang.invoke.MethodHandle instance is the method handle of REF_getstatic, REF_putstatic, REF_invokeStatic, and the class corresponding to this method handle is not initialized, you need to trigger out first Its initialization.

use

After the JVM completes the initialization phase, the JVM begins to execute the user's program code from the entry method.

Uninstall

After the execution of the user program code is completed, the JVM starts to destroy the Class object created, and finally the JVM responsible for running also exits the memory.

Class loading summary

It can be seen from the above examples that analyzing the execution order of a class can roughly follow the steps below:

  • Determine the initial value of the class variable. In the preparation stage of class loading, the JVM initializes the zero value of the class variable. At this time, the class variable will have an initial zero value. If it is a class variable modified by final, it will be directly initialized to the value the user wants.
  • Initialize the entry method. When entering the initialization phase of class loading, the JVM will look for the entire main method entry, thereby initializing the entire class where the main method resides. When a class needs to be initialized, the class constructor () is initialized first, followed by the object constructor ().
  • Initialize the class constructor. The JVM will collect the assignment statements and static code blocks of the class variables in order, and finally form the class constructor to be executed by the JVM.
  • Initialize the object constructor. The JVM will collect the assignment statements and ordinary code blocks of the member variables, and finally collect the construction methods to form them into an object constructor, which is finally executed by the JVM.

If you encounter the initialization of other classes when initializing the class where the main method is located, then load the corresponding class first and return after the loading is complete. Repeatedly looping like this, and finally return to the main method class.

Class loader

classification

  • Start class loader: Bootstrap ClassLoader, which is used to load the core library of Java, mainly the classes under <JAVA_HOME> \ lib. This loader cannot be directly referenced by Java programs.

  • Extension class loader: ExtClassLoader, which is used to load Java extension classes, mainly under <JAVA_HOME> \ lib \ ext.

  • Application class loader: AppClassLoader, which is responsible for loading the class specified by the user class path, developers can directly use the class loader, if there is no custom class loader in the application, then this is the default class loading in the program Device.

Parent delegation model

When it comes to class loaders, the parent delegation model is bound to be mentioned. The parent delegation model means that when we call the classloader's loadClass method for class loading, the class loader will first request its parent class loader to load, and then recursively. If all parent class loaders fail to load, the current class loader performs the loading operation itself. Doing so can ensure the security of the Java core classes, for example, you cannot overwrite the java.lang.String class.

Let's take a look at the parent delegation model from the source code of loadClass

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
        // 首先检查这个类是不是已经被加载了
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                // 找当前类加载器的父类去加载
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    //根类加载器没有父类了,所以由根类加载器加载
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            if (c == null) {
                long t1 = System.nanoTime();
                //如果父类加载器加载失败,再由当前类加载器加载
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}
复制代码

Custom class loader

If the custom class loader does not destroy the parent delegation model, you only need to inherit the ClassLoader class and override the findClass method.

If the custom class loader wants to destroy the parent delegation model, you need to inherit the ClassLoader class and override the loadClass method and the findClass method.

When it comes to destroying the parental delegation model, you may be asked if you know any examples of how to break the parental delegation model, and how?

  • Java SPI needs to load third-party vendors' classes (such as commonly used databases) during the loading of the core class library rt.jar, and directly specify the application class loader to load these classes.
  • The web container class loader in Tomcat also destroys the parental delegation model. In addition to the core class library, the custom WebApplicationClassLoader loads the Class in its own path first

Guess you like

Origin juejin.im/post/5e9c330ae51d4546eb5257de