Analysis of the principle of Java JVM class loading mechanism

Preface

      To load a Java class into the JVM, it will go through a series of loading processes. This process is implemented in the class loading subsystem. When we use the Java command to run the main function of a certain class to start the program, we first need to load it through the class The server loads the main class into the JVM. This article will analyze this loading process and the parent delegation mechanism.
Insert image description here

1. What is class loading?

      Class loading is actually to find the bytecode file (class file) read through io on the hard disk and load it into the JVM method area/metaspace as a metadata template. N identical instance objects can be instantiated based on this template. A class is loaded only once, and dynamically the first time it is used.

  • How to load .calss files:
    • Load directly from local system
    • Download .class through the Internet
    • Load .class from archive files such as zip, jar, war etc.

2. Class loading subsystem

Insert image description here

  • The class loader subsystem is responsible for loading Class files from the file system or network. Class files have a specific file identifier at the beginning of the file.

  • The loading phase is only responsible for loading the class file. Whether it can be run is determined by the bytecode execution engine.

  • The loaded class information is stored in a memory space called the method area/meta space. In addition to class information, the method area/metaspace also stores runtime constant pool information, which may also include string literals and numeric constants (this part of constant information is the memory mapping of the constant pool part in the Class file), different versions JDK also has its own differences.

3. Class loading process

      When the JVM needs to use a certain class, the virtual machine loads its .class file. After loading the relevant bytecode information, it creates the corresponding Class object for it, and this process is called Class loading. However, additional attention should be paid to the fact that the class loading mechanism is only responsible for loading class files. Whether it can be executed is determined by the execution engine.
      The life cycle of a class includesLoading>> Verification>> Preparation>> Parsing>> Initialization>> Use> ;> Unloading These 7 stages, in which the class loading process isLoading>> Verification>> Preparation>> Parsing> > Initialization.
Insert image description here

2.1. Loading

The loading phase is performed by the class loader. The ways to load .class files are:

Load directly from the local system
Obtain through the network
Read from the zip package, such as: jar, war format files a>
Runtime calculation generation, such as: dynamic proxy technology

  • The loading process does three things:
    • 1. Obtain the binary byte stream that defines the class through its fully qualified name.
    • 2. Convert the static storage structure represented by the byte stream into the runtime storage structure of the method area.
    • 3. Generate a Class object representing the class in the memory, which serves as the access point for various data of the class in the method area/metaspace.

2.2. Verification

The JVM will verify the binary byte stream at this stage, and only those that comply with the JVM bytecode specifications can be executed correctly by the JVM. This stage is an important barrier to ensure the security of the JVM. Here are some major checks.

  • Make sure the binary byte stream format is as expected (e.g. starts with cafe bene).
  • Whether all methods comply with access control keyword qualifications.
  • Whether the number and type of parameters in the method call are correct.
  • Make sure variables are properly initialized before use.
  • Checks whether the variable is assigned a value of the appropriate type.

2.3. Preparation

  • The JVM will allocate memory and initialize class variables (also called static variables, modified with the static keyword) at this stage (corresponding to the default initial value of the data type, such as 0, 0L, null, false, etc.), and will not be allocated at this time. Memory for instance variables because instance variables are created in the Java heap together when the object is instantiated. Conceptually, the memory used by class variables should be allocated in the method area/metaspace. However, one thing to note is that before JDK 7, when HotSpot used the permanent generation to implement the method area, the implementation was completely consistent with this logical concept. In JDK 7 and later, HotSpot has moved the string constant pool, static variables, etc. that were originally placed in the permanent generation to the heap. At this time, the class variables will be stored in the Java heap along with the class object.
  • The initial value set here is "normally" the default zero value of the data type (such as 0, 0L, null, false, etc.). For example, we define public static int i=996 , then the initial value of the i variable in the preparation phase is 0 instead of 996 (the value is assigned only in the initialization phase). Special case: For example, if the final keyword public final static int i=996 is added to the value variable, then the value of the preparation phase i will be assigned 996.

2.4. Analysis

  • This phase converts symbol references in the constant pool into direct references.
  • Literal and symbolic references are stored in the constant pool in the class file. Symbolic references include the fully qualified names of classes and interfaces, as well as the names and descriptors of fields and methods.
  • During JVM dynamic linking, these symbolic references need to be converted into direct references to store memory usage.

2.5. Initialization

  • The initialization phase is the process of executing the class constructor method ();
  • This method does not need to be defined. It is merged by the javac compiler to automatically collect the assignment actions of all class variables in the class and the statements in the static code block;
  • The instructions in the constructor method are executed in the order in which the statements appear in the source file;
  • Initialization, assigning correct initial values ​​to the static variables of the class, the JVM is responsible for initializing the class, mainly initializing the class variables. There are two ways to initialize class variables in Java:
    • Declare a class variable to specify an initial value
    • Use static code blocks to specify initial values ​​for class variables
public class ClassInitDemo {
    
    
    private static int a = 1;

    // 静态代码块 在类初始化时调用
    static {
    
    
        System.out.println(a); //1
        a = 10;
        b = 20;
        System.out.println(a); //10
        //System.out.println(number);    //报错:非法的前向引用(可以赋值,但不能调用)
    }

    //链接阶段的准备环节:b = 0 --> 初始化阶段:2 --> 20
    private static int b = 2;

    // 代码块 会在实例前调用
    {
    
    
        System.out.println("代码块");
    }

    public ClassInitDemo(){
    
    
        System.out.println("ClassInitDemo");
    }

    public static void main(String[] args) {
    
    
        System.out.println(ClassInitDemo.a); // 10
        System.out.println(ClassInitDemo.b); // 20
        ClassInitDemo classInitDemo = new ClassInitDemo();
    }
}

Class initialization timing

Only active use of a class will result in initialization of the class. Active use of the class includes the following six types:

  • Create an instance of a class, which is the new method
  • Access a static variable of a class or interface, or assign a value to the static variable
  • Call a static method of a class
  • When using the methods of the java.lang.reflect package to make reflection calls to a class (such as Class.forName("com.kerwin.Test"), newInstance())
  • Initialize a class. If its parent class has not been initialized, the initialization of the parent class will be triggered first.
  • When the virtual machine starts, the user needs to define a main class to be executed (the class containing the main method), and the virtual machine first initializes this class.
  • When an interface defines a new default method added by JDK8 (an interface method modified by the default keyword), if an implementation class of this interface is initialized, the interface must be initialized before it.

4. ClassLoader

Insert image description here

  • Boot/startup class loader: Bootstrap ClassLoader, responsible for loading files stored in jdk\jre\lib (jdk represents the installation directory of jdk, the same below), or in the path specified by the -Xbootclasspath parameter, and can be recognized by the virtual machine Class library (such as rt.jar, all classes starting with java.*, such as java.lang.Integer are loaded by Bootstrap ClassLoader). The startup class loader cannot be directly referenced by Java programs.

    Note: Because the JVM loads class libraries through fully qualified names, if your file name is not recognized by the virtual machine, even if you drop the jar package into the lib directory, the boot class loader will not load it. For security reasons, the Bootstrap startup class loader only loads class files whose package names begin with java, javax, sun, etc.

  • Extension class loader: Extension ClassLoader, which is implemented by sun.misc.Launcher$ExtClassLoader, which is responsible for loading all classes in the JDK\jre\lib\ext directory or the path specified by the java.ext.dirs system variable Libraries (such as classes starting with javax.*), developers can directly use the extension class loader.

    This class loader is implemented by sun company and is located in the sun.misc.Launcher$ExtClassLoader location in the HotSpot source code directory. It is mainly responsible for loading class libraries in the <JAVA_HOME>\lib\ext directory or in the path specified by the system variable -Djava.ext.dir. It can be used directly by developers.

  • System/Application Class Loader: Application ClassLoader, also known as the application class loader, is also implemented by sun company and is located at the sun.misc.Launcher$AppClassLoader location in the HotSpot source code directory. It is responsible for loading the class library under the path specified by the system class path java -classpath or -D java.class.path, which is the commonly used classpath path. Application class loaders can also be used directly by developers.

    Generally, this class loader is the default class loader of the program, and we can obtain it directly through the ClassLoader.getSystemClassLoader() method.

  • Custom class loader: Application ClassLoader, also known as application class loader, is also implemented by sun company and is located in the sun.misc.Launcher$AppClassLoader location in the HotSpot source code directory. It is responsible for loading the class library under the path specified by the system class path java -classpath or -D java.class.path, which is the commonly used classpath path. Application class loaders can also be used directly by developers.

Guess you like

Origin blog.csdn.net/weixin_44606481/article/details/134838287