This is the 11th day of my participation in the August More Text Challenge

Class loading timing

The 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 virtual machines. This is the Class loading mechanism of virtual machines.

In the Java language, type loading, concatenation, and initialization are all done at runtime

The process of class loading

Class life cycle PS: NoClassDeFoundError: Occurs during the parse phase of the class life cycle when the corresponding class is not foundClassNotFoundException Occurred during the loading phase of the class life cycle and the corresponding class could not be found.

To support runtime binding, the parsing process can start after initialization in some cases, and all loading processes other than parsing must begin in the order shown.

loading

  1. Gets the binary byte stream that defines this class by fully qualified class name.
  2. Will this byte stream representStatic storage structures are transformed into method areasThe runtime data structure of.
  3. In memoryGenerate a java.lang.Class object that represents this ClassAs an access point to the class’s various data.

validation

Validation is the first step in the connection phase, which ensures that the byte stream in the Class file meets the requirements of the current virtual machine and does not compromise the security of the virtual machine itself.

  1. File format verification: for example, whether the file starts with magic number 0xCAFEBABE, whether the major and minor versions are within the processing scope of the current VM, and verifying the rationality of constants.

This phase ensures that the input byte stream is properly parsed and stored in the method area in a format that describes the information of a Java type.

  1. Metadata verification: whether there is a parent class, whether the inheritance chain of the parent class is correct, whether the abstract class implements all the methods required by the parent class or interface, whether the fields and methods conflict with the parent class, etc.

The second stage ensures that there is no metadata information that does not conform to the Java language specification.

  1. Bytecode validation: Determine that program semantics are legitimate and logical through data flow and control flow analysis. Such as ensuring that a jump instruction does not jump to a bytecode instruction outside the method body.
  2. Symbolic reference validation:Occurs during the parsing phaseTo ensure that symbolic references can be converted to direct references.

Consider using the -xVerify: None parameter to turn off most of the class validation measures to shorten the virtual machine class load time.

To prepare

Allocates memory for class variables and sets their initial values. The memory used by these variables is allocated in the method area.

Public static int value = 123 Public static int value = 123 Public static int value = 123 The putStatic instruction, which assigns value to 123, is compiled and stored in the clinit() method of the class constructor, and will be executed at initialization

Public final static int value = 123 Public final static int value = 123 Public final static int value = 123 Public final static int value = 123 Public final static int value = 123

parsing

The process by which the virtual machine replaces symbolic references in a constant pool with direct references.

The parse action is mainly for class or interface, field, class method, interface method, method type, method handle, and call point qualifier 7 class symbol references. To support runtime binding, the parsing process can start after initialization in some cases, and all loading processes other than parsing must begin in the order shown

NoClassDeFoundError: occurs when the corresponding class is not found during the parsing phase of the class life cycle

Initialize the

The actual execution of the Java program code defined in the class begins in the initialization phase, where the Clinit () method is executed. The Clinit () method is generated by the compiler automatically collecting the assignment actions of all class variables in a class in the order in which the statements appear in the source file and combining statements in a static code block. (Not including statements in constructors. The constructor initializes the object. After the class is loaded, the init() method is called when the object is created.

A static block can only access variables defined before the static block, and variables defined after it. The preceding static block can be assigned, but not accessedAs follows:This is normal; But if I change the statementThis will prompt youIllegal forward reference; Then explainThe Clinit () method is generated by combining the assignment of all class variables in a class that the compiler automatically collects in the order in which the statements appear in the source file with statements in a static code blockTo sum up:

  1. Initiating an order is the process of executing the Clinit () method
  2. The Clinit () method is generated by the compiler automatically collecting the assignment actions of all class variables in a class in the order in which the statements appear in the source file and combining statements in a static code block
  3. Clinit () does not explicitly call the parent’s initialization method clinit(), and the virtual machine guarantees that the parent’s Clinit () method will complete before the subclass’s Clinit () method executes, meaning that the static statement block defined in the parent takes precedence over the subclass’s variable assignment.
  4. The Clinit () method is not required for a class or interface, and the compiler may not generate the Clinit () method for a class that has no static blocks and no assignment to variables
  5. 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 finishes executing the clinit() methods.

For the initialization phase, the virtual machine specification specifies that there are five and only five cases in which classes must be “initialized” immediately (while loading, validation, and preparation naturally need to begin before that)

  1. When the bytecode instructions new, getStatic, and putstatic or Invokestatic are encountered, initialization needs to be triggered if the class has not already been initialized. The scenarios are: instantiating an object with new, reading or setting static fields of a class (except static fields that are modified by final and have put results into the constant pool at compile time), and calling static methods of a class.
  2. When a reflection call is made to a class, initialization needs to be triggered if the class has not already been initialized.
  3. If the parent of an initializing class has not been initialized, the initialization of its parent class needs to be triggered first. (When an interface is initialized, its parent interface is not required to be initialized.)
  4. When the virtual machine starts, the user needs to specify a main class (the one containing the main() method) to execute,

The virtual machine initializes the main class first.

  1. When using JDK 1.7 dynamic language support, if a Java lang. Invoke. The final analytical results REF_getStatic MethodHandle instance, REF_putStatic, REF_invokeStatic method handles, If the class to which the method handle corresponds has not been initialized, it needs to be initialized first.

Class loader

Even if two classes come from the same Class file and are loaded by the same virtual machine, they are not equal as long as they are loaded by different classloaders.

Parental delegation model

The parent delegate model loads the class logic as follows:

    // The code is from "Understanding the Java Virtual Machine in Depth"
    protected synchronizedClass<? > loadClass(String name,boolean resolve) throws ClassNotFoundException {
        // First, check whether the requested class has already been loaded
        Class c = findLoadedClass(name);
        if (c == null) {
            try {
                if(parent ! =null) {
                    c = parent.loadClass(name, false);
                } else{ c = findBootstrapClassOrNull(name); }}catch (ClassNotFoundException e) {
            // If the parent class loader throws a ClassNotFoundException
            // Indicates that the parent class loader cannot complete the load request
            }
            if (c == null) {
                // When the parent class loader cannot be loaded
                // Call its own findClass method for class loadingc = findClass(name); }}if (resolve) {
            resolveClass(c);
        }
        return c;
    }
Copy the code

Custom class loaders

  1. Inherited Java. Lang. This
  2. The JDK loadCalss() method calls its own findClass() method when all the parent loaders fail to load, so we just need to override the findClass() method to find the binary data of the class.

Refer to the article

  1. In-depth understanding of virtual machines