In-depth analysis of the second class loader of JVM

Class loader in-depth analysis

Lecture notes

First of all, I recommend the two monitoring JVM tools jConsole and jvisualvm that come with the JDK, and the monitoring command jmap that comes with the JDK.
1. In the Java code, the type (referring to the type of the object does not refer to an object, because at this time the class file has not been loaded in memory yet, and it cannot be used to create an object) loading, connection and initialization process are all in
2. Completed during the running of the program provides greater flexibility and increased more possibilities.

In the following situations, the java virtual machine will end its life cycle (the java virtual machine itself is a process):
1. The System.exit() method
is executed 2. The program execution ends normally
3. The program program encounters during execution Abnormal termination due to an exception or error (when the error or exception is not handled and is thrown to the main (thread) method, the JVM process will terminate. In the web project of the spring framework, a new thread will be regenerated every time the JVM is requested, and an error will be reported. It just causes the current thread to terminate, and the error will not be thrown to the main (process) method. Therefore, the JVM process in the spring web project will not be terminated due to an interface error. Only when the exception appears in the main (process) method Will cause the JVM to terminate.)
4. The Java virtual machine process is terminated due to an error in the operating system

One, the life cycle of the class in the JVM
  • The loading of the loading
    class refers to reading the binary data in the class file of the class into the memory, placing it in the method area of ​​the runtime data area, and then creating a java.lang.Class object in the memory (specification and It is not stated where the Class object is located. The HotSpot virtual machine puts it in the method area) to encapsulate the data structure of the class in the method area.
    How to load class files
    1. Load directly from the local system
    2. Download class files through the network
    3. Load class files
    from archive files such as zip, jar 4. Extract class files from a proprietary database
    5. Dynamic Java source files Compiled to a class file (for example: JSP is compiled into a class file corresponding to the servlet Java class at runtime and then loaded by the JVM)
  • Connection
    1. Verification: Ensure the correctness of the loaded class
    2. Preparation: Allocate memory for the static variables of the class and initialize it to the default value (for example, the default value of the int type is 0)
    3. Analysis: Put the symbols in the class Conversion of references to direct references
  • Use
    active use (how to calculate active use should be analyzed at the bytecode level, conversion can be divided into about six scenarios at the code level)
    1. Create an instance of
    a class 2. Access static variables of a certain class or interface (including Run-time static constants, except for compile-time static constants), or assign a value to the static variable and call the static method of the class (the class here refers to the class that defines the static variable or static method as shown in the figure below. The main method executes the run method, by 2 that run method is myParent defined class, where it is to be myParent active use of the class, not for myChild active use of the class, not initialized myChild class)
    Insert picture description here
    Insert picture description here
    3. reflective (e.g. Class.forName ( "yang.jvm. diyijiang.Demo”))
    4. Initialize a subclass of a class (when the subclass is initialized, it is equivalent to the active use of the parent class)
    Note: When the Java virtual machine initializes a class, all its parent classes are required to be Initialization, but this rule does not apply to interfaces.
     When initializing a class, it does not first initialize the interface it implements.
     When initializing an interface, it does not first initialize its parent interface.
    Therefore, a parent interface is not due to its sub-interfaces or implementation classes. Only when the program actively uses the static variables of the parent interface for the first time, it will cause the initialization of the interface.

5. The class that is indicated as the startup class when the Java virtual machine is started (the class that contains the main method, such as executing the command Java Demo)
6. The dynamic language support provided by JDK1.7: The analysis of the Java.lang.invoke.MethodHandle instance As a result, the classes corresponding to the REF_getStatic, REF_putStatic, and REF_invokeStatic handles are not initialized, so they are initialized.
Passive use : In addition to the above six cases, other methods of using Java classes are regarded as passive use of classes

  • Initialization: Assign correct initialization values ​​to the static variables of the class (from the default value assigned during connection-preparation to the value set by the programmer), and execute the static code block in the class.
    1. All Java virtual machine implementations must be initialized when each class or interface is "actively used for the first time" by the Java program, that is, a certain class or interface will only be initialized by the JVM when it meets the six scenarios introduced by the active use . .
    2. The initialized class must be loaded and connected, and the uninitialized class may be loaded and connected, or it may not be loaded and connected.
    3. Each class or interface is initialized only once by the JVM. After the first use, it will not be initialized again, but will be used directly.
    4. When a class is being initialized, all its parent classes are required to be initialized.

  • Uninstall: Destroy the class bytecode file in the JVM, and the type after the destruction can no longer be used.

Second, the code demonstrates active and passive use and explains
Example 1:
public class Demo {
    
    
	
  public static void main(String[] args) {
    
    
	System.out.println(myChild.str2);
  }
}
 

class myParent{
    
    
	public static String str1="myParent";
	static{
    
    
		System.out.println("myParent static block");
	}
}


class myChild extends myParent{
    
    
	public static String str2="myChild";
	static{
    
    
		System.out.println("myChild static block");
	}
}

Run the program to print the result:
myParent static block
myChild static block
myChild
Explanation:
First, myChild.str2 in main satisfies the second scenario of active use for the myChild class, so the myChild class is initialized; the myChild class is initialized to meet the myParent class The fourth scene is actively used, so myParent is initialized. Because when a class initialization, requires the parent class has been initialized all finished , it will first initialize myParent class, so as to print out the results.

Example 2:
public class Demo {
    
    
	
  public static void main(String[] args) {
    
    
	System.out.println(myChild.str1);
  }
}
 

class myParent{
    
    
	public static String str1="myParent";
	static{
    
    
		System.out.println("myParent static block");
	}
}


class myChild extends myParent{
    
    
	public static String str2="myChild";
	static{
    
    
		System.out.println("myChild static block");
	}
}

Run the program to print the result:
myParent static block
myParent
Explanation:
Compared with example 1, myChild is not initialized. For explanation, see the second item of the six active usage scenarios above. The static variables are the same as the static run method above.

3. Question: The myChild class in the second example is not initialized. Is it loaded and connected? The answer will be verified in the second chapter.

Guess you like

Origin blog.csdn.net/yangxiaofei_java/article/details/103342035