Because love so insist, because love so wait. Through the long days without drama to play, finally for the spring of life, mutual encouragement!!

  • Class loading subsystem structure diagram

1. What are the steps of class loading?

According to the Java Virtual Machine specification, the entire life cycle of a class file, a class loaded into memory, and a class unloaded from memory consists of the following seven phases: Data types in Java are divided into basic data types and reference data types. Basic data types are predefined by the VIRTUAL machine, while reference data types require class loading

2. Class Loading

  • (1).The loading of a class refers to the loading ofThe binary data in the.class file of the class is read into memory and stored in the methods section of the runtime data sectionAnd create a big oneJava. Lang. Class object, which is used toEncapsulates the data structures in the method areaWhen loading a class, the Java virtual machine must do three things:
    • 1. Get the binary byte stream that defines a class by its fully qualified name
    • 2. Convert the static storage structure represented by this byte stream to the runtime data structure of the method area
    • 3. Generate a java.lang. Class object representing the Class in memory as the method section of the Class

    Access points for various data

In short, the bytecode file of a Java class is loaded into machine memory, and the prototype of the Java class — class template object is built in memory

  • (2) For binary data streams of classes, the virtual machine can generate or obtain them in a variety of ways (as long as the bytecode read conforms to the JVM specification). The loading methods are as follows:

    Download the file from the local system. 2. Download the file from the network, for example, Web Applet 3. Read from zip packages and become the basis for future JAR and WAR formats 4. Runtime computing generation, the most used is: dynamic proxy technology 5. Generated by other files, typical scenario: JSP application 6. Extracting. Class files from a proprietary database, which is rare 7. Extracting from an encrypted file is a typical protection against class files being decompiled

3. Links (Linking)

  • ①. Verification: Ensure that the byte stream of the Class file contains information that meets the requirements of the current VM to ensure the correctness of the loaded Class

    1. To ensure that the byte stream in the Class file meets the requirements of the CURRENT VM, ensure that the loaded Class is correct and does not harm vm security

    2. Mainly includes four kinds of verification: file format verification, metadata verification, bytecode verification, symbol reference verification

    3. Format check: whether it starts with Magic oxCAFEBABE, whether the major and minor versions are supported by the current Java virtual machine, whether each item in the data has the correct length, etc

  • ②. Preparation :(static variable, not constant)

    1. Allocate memory for class static variables and set default initialization values for class variables

    Static with final is not included because final is assigned at compile time and is explicitly assigned during preparation

    3. There is no instance variable allocation initialization, class variables are allocated in the method area, and instance variables are allocated in the Java heap along with the object

    4. Note that Java does not support Boolean types. For Boolean types, the internal implementation is int, and the default value of int is 0

  • Parsing: The process of converting symbolic quotes from a constant pool into direct references (in short, converting symbolic references to classes, interfaces, fields, and methods)
  1. The virtual machine does dynamic linking only when the Class file is loaded. That is, the final memory layout of the various methods and fields is not stored in the Class file. Therefore, symbolic references to these fields and methods cannot be directly used by the virtual machine without conversion. When the virtual machine is up and running, the corresponding symbolic reference needs to be retrieved from the constant pool, replaced by a direct reference during class loading (initialization) and translated into a specific memory address
  2. Symbolic reference: A symbolic reference describes the referenced object as a set of symbols, which can be any literal, as long as it is used to unambiguously locate the object. Symbolic references are independent of the memory layout implemented by the virtual machine, and the target of the reference is not necessarily already loaded into memory
  3. Direct reference: A direct reference can be a pointer to a target, a relative offset, or a handle that can be indirectly located to the target. A direct reference is related to the memory layout implemented by the VIRTUAL machine. The translation of a symbolic reference on different virtual machine instances will not be the same. If there is a direct reference, the target of the reference must already exist in memory.
  4. However, the Java Virtual Machine specification does not explicitly require that the parsing phase be performed sequentially. In HotSpot VM, loading, validation, preparation, and initialization are done in an orderly fashion, but parsing in the linking phase is often followed by the JVM after initialization
  5. Symbolic quotes include fully qualified names of classes and interfaces, field names and descriptors, and method names and descriptors

4. Initialization

  • Assign the correct initialization value to the class variable

  • The initialization phase is the execution of the class constructor method < clinit >(). This method does not need to be defined and is a combination of the statements in the static code quick and the assignment actions that the Javac compiler automatically collects for all class variables in a class

public class ClassInitTest {
    private  static int num=1; // Class variable assignment action
    // Static code fast statements
    static{
        num=2;
        number=20;
        System.out.println(num);
        //System.out.println(number); Error: Invalid forward reference
    }
    //Linking: number=0 -->initial:20-->10
    private static int number=10;

    public static void main(String[] args) { System.out.println(ClassInitTest.num); System.out.println(ClassInitTest.number); }}Copy the code

  • ③ If the class has a parent class, the Jvm guarantees that < clinit >() of the parent class has been executed before < clinit >() of the subclass is executed.
public class ClinitTest1 {
    static class Father{
        public static int A=1;
        static{
            A=2; }}static class Son extends Father{
        public static int B=A;
    }

    public static void main(String[] args) {
        // This output is 2, indicating that all the parent classes have been loadedSystem.out.println(Son.B); }}Copy the code
  • The Java compiler does not generate < Clinit >() initialization methods for all classes. Which classes, when compiled to bytecode, will not contain the () method in the bytecode file?

1. When a class does not declare any class variables or static code blocks

2. When a class declares a class variable, but does not explicitly use the class variable initialization statement ** and the static code block ** to perform initialization 3. A class containing fields ** of the base datatype modified by **static final. These class field initialstatements take ** compile-time constant expressions **Copy the code

(In the link phase if the static final is not through a method or constructor)

  • ⑤.< clinit >() differs from the class constructor
  • Can calls to clinit() be deadlocked?

1. The virtual machine ensures that a class’s < Clinit >() methods are locked and synchronized correctly in a multithreaded environment. If multiple threads initialize a class at the same time, only one thread will execute the class’s < Clinit >() methods, and all the other threads will block until the active thread executes < Clinit >() >() method complete

2. Because the method < clinit >() is thread-safe, lengthy operations within a class’s < clinit >() methods can cause multiple threads to block, causing deadlocks. And deadlocks are hard to find because they don’t seem to have lock information available

package com.xiaozhi;

/ * * *@author TANGZHI
 * @createThe 2021-05-25 * /
class StaticA {
    static {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        try {
            Class.forName("com.xiaozhi.StaticB");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("StaticA init OK"); }}class StaticB {
    static {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        try {
            Class.forName("com.xiaozhi.StaticA");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("StaticB init OK"); }}public class StaticDeadLockMain extends Thread {
    private char flag;

    public StaticDeadLockMain(char flag) {
        this.flag = flag;
        this.setName("Thread" + flag);
    }

    @Override
    public void run(a) {
        try {
            Class.forName("com.xiaozhi.Static" + flag);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(getName() + " over");
    }

    public static void main(String[] args) throws InterruptedException {
        StaticDeadLockMain loadA = new StaticDeadLockMain('A');
        loadA.start();
        StaticDeadLockMain loadB = new StaticDeadLockMain('B'); loadB.start(); }}Copy the code

5. Active references (triggering Clinit methods during initialization)

When creating an instance of a class, such as using the new keyword, or by reflection, cloning, or deserialization

Access or assign a value to a static variable of a class or interface

Call the static method of the class

④ reflection (e.g. Class.forname (” com.xiaozhi.Test “))

⑤. Initialize a subclass (when initializing a subclass, if it is found that its parent class has not been initialized, it needs to trigger the initialization of its parent class first)

⑥ When the virtual machine starts, the user needs to specify a main class (the class containing the main() method) to execute. The virtual machine initializes this main class first

(7) Dynamic language support for REF_getStatic, REF_putStatic, REF_invokeStatic method handles

If an interface defines a default method, the class that implements the interface, either directly or indirectly, must be initialized before it

6. Passive quoting

① in addition to the above cases belong to active use, other cases are passive use. Passive use does not cause class initialization. Means there is no call to < clinit >().

Calling the loadClass() method of the ClassLoader class to load a class is not an active use of the class and does not result in class initialization

When accessing a static field, only the class that actually declares the field is initialized. When a static variable of a parent class is referred to by a subclass, it does not cause the subclass to be initialized

④ Reference constants do not trigger initialization of this class or interface. Constants are explicitly assigned at the link stage

Defining a class reference through an array does not trigger initialization of this class

[]parent= = = = = = = = = = = = = = = = = =new Parent[10];
Copy the code

7. Uninstall (Unloading)

①. Garbage collection in the method area

  1. The method area garbage collection collects two main parts: obsolete constants in the constant pool and types that are no longer used.
  2. The HotSpot VIRTUAL machine has a very clear policy for reclaiming constants from the constant pool as long as they are not referenced anywhere
  3. It is relatively easy to determine whether a constant is “obsolete,” while the criteria for determining whether a type is “no longer in use” are more demanding. The following three conditions must be met

②. Class uninstallation

  1. Startup class loaders load types that cannot be unloaded during the entire run (JVM and JLS specifications)
  2. The types loaded by system classloaders and extension classloaders are unlikely to be unloaded during runtime, because instances of system classloaders or extension classes can almost always be accessed directly or indirectly during runtime, and the possibility of reaching unreachable is minimal
  3. The type of class loader instance loaded by a developer can only be unloaded in a very simple context, and usually with the help of a forced invocation of the virtual machine’s garbage collection. It can be expected that in slightly more complex application scenarios (e.g., many times users use caching when developing custom classloader instances to improve system performance), loaded types are almost unlikely to be unloaded at runtime (at least for an indefinite period of time).

The next articleJVM class loading subsystem (part 2) – class loader, parent delegate mechanism, sandbox security mechanism details

Reference video: Silicon Valley JVM complete tutorial, millions of playback, the peak of the network (Song Hongkang details Java VIRTUAL machine) reference books: in-depth understanding of the Java virtual machine