1 Overview
The Virtual Machine loads the description class data from the class file to the virtual machine, verifies, converts, parses, and initializes the data, and finally forms the Java type that can be directly used by the virtual machine, this is the class loading mechanism of virtual machines.
Different from the languages that need to be connected during compilation, in Java, the class loading and connection processes are completed during the program running, this will slightly increase some performance overhead in class loading, but it can provide a high degree of flexibility for Java applications, the language feature that Java Zhongtian can dynamically expand is achieved by running dynamic loading and Dynamic Linking.
Loading time of Class 2
The entire lifecycle of a class starts from loading it to the VM memory and ends with detaching the memory:
Load, verification, preparation, resolution, initialization, using, and unloading ).
Under what conditions will classes be "initialized" immediately after loading (and loading, verification, and preparation naturally need to begin before this ):
1. When four bytecode commands, namely new, getstatic, putstatic, or invokestatic, are run, if the class has not been initialized, the trigger must be initialized first.
2. When calling a class using the java. util. Reflect package method.
3. When initializing a class, if you find that the parent class has not been initialized, you must first trigger the initialization of the parent class.
4. When a VM is started, you need to specify a main class to be executed (the class containing the main method). The virtual opportunity first initializes the main class.
In addition, the reference class method will not be initialized and become passive reference:
Demo1: passive reference
Referencing static fields of the parent class by subclass does not cause subclass initialization, nor does the constructor of the parent class Execute
Package CN. partner4java. classloading; public class superclass {public superclass () {system. out. println ("superclass Construction");} static {system. out. println ("superclass static");} public static int value = 1;} package CN. partner4java. classloading; public class subclass extends superclass {public subclass () {system. out. println ("subclass Construction");} static {system. out. println ("subclass static") ;}} package CN. partner4java. classloading;/*** use a subclass to reference the static field of the parent class, the constructor of the parent class does not execute * @ author partner4java **/public class notinitialization {public static void main (string [] ARGs) {system. out. println (subclass. value); // It is printed later: // superclass static // 1 }}
Demo2: references a class through array definition and does not trigger initialization of this class.
Package CN. partner4java. classloading;/*** the class is referenced through array definition, and class initialization is not triggered * @ author partner4java **/public class notinitialization2 {public static void main (string [] ARGs) {superclass [] supers = new superclass [10]; // nothing is printed in the background }}
Demo3:
Constants are stored in the constant pool of the call class during compilation. In essence, they are not directly referenced to classes that define constants. Therefore, initialization of the definition constant class is not triggered.
Package CN. partner4java. classloading; public class constclass {public constclass () {system. out. println ("constclass Construction");} static {system. out. println ("constclass static area");} public static final string hello_world = "Hello World";} package CN. partner4java. classloading;/*** constants are stored in the constant pool of the call class during compilation. Essentially, they do not directly reference classes that define constants, therefore, initialization of defining constant classes is not triggered * @ author partner4java **/public class notinitialization3 {public static void main (string [] ARGs) {system. out. println (constclass. hello_world); // background printing: // Hello world }}
Demo4:
When a static method is called, the static region Initialization is triggered, but the constructor is still not initialized.
Package CN. partner4java. classloading; public class constclass {public constclass () {system. out. println ("constclass Construction");} static {system. out. println ("constclass static area");} public static final string hello_world = "Hello World"; public static void mehtodt () {system. out. println ("constclass static mehtodd");} public static void mehtodt2 () {system. out. println ("constclass static mehtod2") ;}} package CN. partner4java. classloading;/*** when a static method is called, static region Initialization is triggered, however, the constructor still does not initialize * @ author partner4java **/public class notinitialization4 {public static void main (string [] ARGs) {constclass. mehtodt (); // background printing: // constclass static area // constclass static mehtodd }}
Demo5:
Whether to initialize during reflection
Getclass does not do anything. Class. forname executes static fields, but does not execute constructor initialization.
Package CN. partner4java. classloading; import Java. lang. reflect. invocationtargetexception; import Java. lang. reflect. method;/*** getclass does not do anything, class. forname executes static fields, but does not execute the constructor initialization * @ author partner4java **/public class notinitialization5 {public static void main (string [] ARGs) throws classnotfoundexception, securityexception, nosuchmethodexception, illegalargumentexception, illegalaccessexception, invocationtargetexception {class clazz = constclass. class. getclass (); system. out. println ("-------"); clazz. getmethods (); system. out. println ("-------"); // Add the following two lines of code to print the following content: Error // method methodt = clazz. getmethod ("mehtodt"); // system. out. println ("--------"); // methodt. invoke (null, null); // ------- // exception in thread "Main" Java. lang. nosuchmethodexception: Java. lang. class. mehtodt () // At java. lang. class. getmethod (class. java: 1605) // At CN. partner4java. classloading. notinitialization5.main (notinitialization5.java: 18) system. out. println ("--------"); Class clazz2 = Class. forname ("CN. partner4java. classloading. constclass "); // even if you execute" constclass static area ", the following code is also incorrect, and it will be said that no Initialization is made. // system. out. println ("--------"); // method methodt = clazz. getmethod ("mehtodt"); // methodt. invoke (null, null); // remove the error section in the background: // ------- // constclass static area }}
Three types of Loading Process
1. Load
Complete three things
Get the binary byte stream that defines this class by using the permission name of a class.
Converts the static storage structure represented by this byte stream into the runtime data structure of the method area.
Generate a java. Lang. Class Object that represents this class in the Java heap, which serves as the access entry to the data in the method area.
2. Verification
Verification is the first step in the connection phase to ensure that the information contained meets the requirements of the current virtual machine and threatens the security of the virtual machine.
There are roughly four verification processes: File Format verification, metadata verification, bytecode verification, and symbol reference verification.
File Format verification mainly involves file format specification and version verification.
Metadata verification mainly performs Semantic Analysis on the information described by bytecode to ensure that the information described complies with the requirements of Java language specifications.
Bytecode verification mainly involves data flow and control flow analysis. The task is to ensure that the verified methods do not harm the security of virtual machines at runtime.
Symbol reference verification occurs when the Virtual Machine converts a symbol reference to a direct reference, it can be seen as a matching verification for information other than the class itself (various symbol references in the constant pool. The goal is to ensure that the parsing action can be executed normally.
3. Preparation
The preparation phase officially allocates memory for class variables and sets the class variable initialization phase, which will be allocated in the method area.
Memory Allocation only includes class variables (static modified variables), rather than instance constants. instance constants will be allocated to the Java heap along with objects during Object Instantiation.
Secondly, the initial value here is generally 0, for example: public static int value = 123; the initial value here is not 123, but 0,123 is executed only during the initialization phase.
However, if it is final, 123 is assigned here.
4. Analysis
In the parsing phase, the virtual machine replaces the symbol reference in the constant pool with the direct reference.
The parsing action mainly applies to class or interface, field, class method, and interface method symbol reference.
5. Initialization
Class initialization is the last step in the class loading process.
In the preparation phase, class variables have been assigned an initial value required by the system, while in the initialization phase, class variables and other resources are initialized by programmers through the subjective program, or, from another perspective, the initialization stage is the process of executing the <clinit> () method of the class constructor.
· The <clinit> () method is generated by the compiler automatically collecting the values of all class variables in the class and merging the statements in the static statement block (static, the sequence collected by the compiler is determined by the sequence in which the statements appear in the source file. In the static statement block, only the variables before the static statement block can be accessed and the variables after the static statement block are defined, in the preceding static statement block, values can be assigned but cannot be accessed.
· The <clinit> () method is different from the class Constructor (or the instance constructor <init> () method). It does not need to display the call to the parent class constructor, the virtual opportunity ensures that the <clinit> () method of the parent class has been completed before the <clinit> () method of the subclass is executed. Therefore, the class of the first <clinit> () method executed in the VM must be Java. Lang. object.
· Because the <clinit> () method of the parent class is executed first, it means that the static statement block defined in the parent class takes precedence over the assignment of the variable of the subclass.
· The <clinit> () method is not required for classes or interfaces. If a class does not have a static statement block or assign values to variables, then the compiler does not generate the <clinit> () method for this class.
· The interface cannot use static statement blocks, but there is still a value assignment operation for variable initialization. Therefore, the <clinit> () method is generated for the interface and the class. When the interface is different from the class, you do not need to execute the <clinit> () of the parent class first ().
· Virtual opportunity ensures the security of the multi-threaded <clinit> () method.
Class 4 Loaders
The virtual machine design team put the "get and describe the binary byte stream of this class through the full qualified name of a class" action in the class loading stage outside the Java Virtual Machine for implementation, so that the application can decide the class required to obtain the lock. The Code module that implements this action is called the class loader ".
1. Class and Class Loaders
Although the class loader is only used to implement the class loading action, its role in Java is far from limited to the class loading stage.
For any class, it is necessary to load its class loader and class itself to establish uniqueness in the Java Virtual Machine.
2. Parental appointment Mode
From the perspective of Java virtual machine, there are only two different class loaders:
One is to start the bootstrap classloader, which is implemented in the C ++ language and is part of the virtual machine itself;
The other is all other class loaders. These class loaders are implemented by the Java language and are independent from the virtual machine and all inherit from the abstract class java. Lang. classloader.
From the perspective of Java programmers, most Java programs use the class loaders provided by the following three systems:
· Bootstrap classloader: In the <java_home> \ lib directory or path specified by the-xbootclasspath parameter, the class library recognized by the virtual machine is loaded into the virtual machine memory. The Class Loader cannot be directly applied by Java programs.
· Extension classloader: This loader has sun. misc. launcher $ extclassloader is used to load the <java_home> \ Lib \ ext directory or. ext. all class libraries in the path specified by dirs system variables can be directly used by developers.
· Application classloader: This class loader is implemented by Sun. Misc. launcher $ appclassloader. Loads the specified class library on the user classpath.
Parents Delegation Model: Except for the top-level class loaders, all other class loaders should have their own parent class loaders. Generally, this parent-child relationship is not an inheritance relationship, but a combination of relationships to reuse the code of the parent loader.
The working process of the parent-child delegation mode is: if a Class Loader receives a class load request, he will not try to load the class himself first, in addition, this request is delegated to the parent class loader for completion. This applies to class loaders at every level. Therefore, all requests should eventually be transferred to the top-level start class loader, if the parent class cannot complete the load request (that is, the class is not found in the search range), the sub-loader will try to load it.
3. Destruction of the parent-child delegation Mode
Such as JNDI and JDBC
Osgi is the loading mode of the mesh structure.
Attachment: general manual Loading Method
Forname
Public static class <?> Forname (string name,
Boolean initialize,
Classloader loader)
Throws classnotfoundexception uses the given class loader to return class objects associated with classes or interfaces with the given string name. (In the format returned by getname) If a fully qualified name of a class or interface is specified, this method attempts to locate, load, and link the class or interface. The specified class loader is used to load the class or interface. If the loader parameter is null, the class is loaded by the bootstrap loader. This class is initialized only when the initialize parameter is true and is not previously initialized.
If name indicates a basic type or void, the user-defined class named name is located in the unnamed package. Therefore, this method cannot be used to obtain any class object that represents the basic type or void.
If name indicates an array class, the component type of the array class is loaded but not initialized.
For example, in an instance method, the expression:
Class. forname ("foo ")
It is equivalent:
Class. forname ("foo", true, this. getclass (). getclassloader ())
Note that this method will throw errors related to loading, linking, or initialization, which are described in sections 12.2, 12.3, and 12.4 of Java language specification. Note: This method does not check whether the caller can access the requested class.
If the loader is null, there is also a security manager, and the caller's class loader is not null, This method uses the runtimepermission ("getclassloader") permission to call the checkpermission method of the security manager, to ensure that the bootstrap loader can be accessed.
Parameters:
Name-fully qualified name of the required class
Initialize-whether class initialization is required
Loader-Class Loader used to load classes
Return Value:
Indicates the Class Object of the required class.
Throw:
Linkageerror-if the link fails
Exceptionininitializererror-If initialization fails to be triggered by this method
Classnotfoundexception-if the class cannot be located with the specified class loader
Start with the following versions:
1.2
For more information, see:
Forname (string), classloader
--------------------------------------------------------------------------------
Forname
Public static class <?> Forname (string classname)
Throws classnotfoundexception returns the class object associated with the class or interface with the given string name. Calling this method is equivalent:
Class. forname (classname, true, currentloader)
Currentloader indicates the definition class loader of this class.
For example, the following code snippet returns the runtime class descriptor of the Java. Lang. Thread class.
Class T = Class. forname ("Java. Lang. Thread ")
If forname ("X") is called, the class named X is initialized.
Parameters:
Classname-the fully qualified name of the required class.
Return Value:
Class Object with the specified name.
Throw:
Linkageerror-if the link fails
Exceptionininitializererror-if the initialization triggered by this method fails
Classnotfoundexception-if the class cannot be found
--------------------------------------------------------------------------------
It can be instantiated after loading:
Newinstance
Public t newinstance ()
Throws instantiationexception,
Illegalaccessexception creates a new instance of the class represented by this class object. This class is instantiated using a new expression with an empty parameter list. If the class has not been initialized, initialize it.
Note that this method propagates any exceptions thrown by the nullary constructor, including checked exceptions. This method can effectively bypass the exception check during compilation, and the compiler will execute this check in other cases. The constructor. newinstance method wraps any exceptions thrown by this constructor in a (checked) invocationtargetexception to avoid this problem.
Return Value:
A newly allocated instance of the class represented by this object.
Throw:
Illegalaccessexception-This class or its nullary constructor is not accessible.
Instantiationexception-if this class represents an abstract class, interface, array class, basic type, or void, the class does not have the nullary constructor, or the instantiation process fails for some other reason.
Exceptionininitializererror-If initialization fails caused by this method.
Securityexception-if security manager s exists and meets any of the following conditions:
Call S. checkmemberaccess (this, member. Public) to reject the creation of new instances of this type.
The class loader of the caller is different from the class loader of the class, and calls to S. checkpackageaccess () reject access to the class package.