JVM——Class Loading Mechanism (1)

Converting the result of code compilation from native machine code to bytecode is one small step in the evolution of storage formats, but one giant leap in the evolution of programming languages.

- Cross-platform guarantee

content:

1 Overview

2. Timing of class loading

3. The process of class loading

 

1 Overview

Process overview:

① The virtual machine loads the data describing the class from the class file into the memory ; ② verifies, converts, parses and initializes the data; ③ finally forms a Java type that can be directly used by the virtual machine: this is the class loading mechanism of the virtual machine.

 

The language features that are inherently dynamically extensible in Java are implemented by relying on the features of runtime dynamic loading and dynamic linking:

Detailed explanation: Unlike languages ​​that require connection work at compile time, in the java language, the type loading, connection and initialization processes are all completed during program execution.

Excellent: Provides a high degree of flexibility for java applications

Disadvantage: This strategy will slightly increase the performance overhead of class loading

Example: If you write an interface-oriented application, you can wait until runtime to specify its actual implementation class; users can use Java's predefined and custom class loaders, so that a local application can be run at runtime, from the network or Loading a binary stream elsewhere as part of the program code, this way of assembling applications is now widely used in Java programs.

2. Timing of class loading

The whole life cycle of a class starts from being loaded into the virtual machine memory and until it is unloaded from the memory, including: Loading , Verification , Preparation , Resolution , Initialization , Use (Using) and unloading (Unloading) seven stages.

The three parts of verification, preparation and parsing are collectively called connection.

To support runtime binding (dynamic binding) of the Java language, the parsing phase may start after initialization.

The sequence on the diagram represents the starting sequence of each stage, and these stages are usually interleaved and mixed.

 

So what is the timing of loading ?

The loading timing of classes can be freely grasped by the specific implementation of different virtual machines, but the virtual machine specification is strictly stipulated for the initialization phase.

There are and only 5 situations in which a class must be initialized immediately ( active reference to a class ):

①When encountering the four bytecode instructions of new, getstatic, putstatic or invokestatic , if the class has not been initialized, it needs to start its initialization. The most common java code scenarios that generate these 4 instructions are (one-to-one correspondence): when instantiating an object using the new keyword, reading or setting a static field of a class (modified by final, the result has been placed at compile time) (except static fields entered into the constant pool), and when calling a static method of a class.

When using the method of the java.lang.reflect package to make a reflection call to a class, if the class has not been initialized, its initialization needs to be triggered first.

When initializing a class, if you find that its parent class has not been initialized , you need to trigger the initialization of its parent class first.

When the virtual machine starts, the user needs to specify a main class to be executed (the class containing the main() method) , and the virtual machine will initialize this main class first.

⑤ When using the dynamic language support of jdk1.7 at that time, if a java.lang.invoke.MethodHandle instance finally parses the method handles of REF_getStatic, REF_putStatic, and REF_invokeStatic, and the class corresponding to the handle of this method has not been initialized, it is necessary to Trigger its initialization first.

 

In addition to this, all methods of reference classes will not trigger initialization, which is called passive reference. Here are 3 examples:

Referencing the static fields of the parent class through the subclass will not cause the subclass to initialize :

For static fields, only the class that defines the field directly will be initialized.

Referencing a class through an array definition will not trigger the initialization of this class :

SuperClass[] sca=new SuperClass[10];

This code does not trigger the initialization phase of the class org.fenixsoft.classloading.SuperClass, but this code triggers the initialization of another class named "[Lorf.fenixsoft.classloading.SuperClass". It is automatically generated by the virtual machine and directly inherited from the subclass of object. The creation action is triggered by the bytecode instruction newarray.

This class represents a one-dimensional array whose element type is org.fenixsoft.classloading.SuperClass, and the properties and methods applied in the array are implemented in this class. Access to arrays in Java language is relatively safer than C/C++ because this class encapsulates the access method of array elements, and C/C++ translates directly to the movement of array pointers.

③Constants will be stored in the constant pool of the calling class during the compilation phase. In essence, there is no direct reference to the class that defines the constant, so the initialization of the class that defines the constant will not be triggered : In fact, the constant already belongs to NotInitialization after compilation. The constant pool of the class is now, and the reference to the constant through the original class name will be converted into a reference to the NotInitialization class constant.

 

Note: The loading process of the interface is slightly different from the class loading process. Some special instructions need to be made for the interface. The interface also has an initialization process. Although the static{} statement block cannot be used in the interface, the compiler will still generate "<clinit" for the interface. >()" class constructor, which is used to initialize the member variables defined in the interface.

The real difference between an interface and a class is the third one of the five "have and only" scenarios that need to be initialized: when a class is initialized, all its parent classes are required to have been initialized, but an interface During initialization, all parent interfaces are not required to be initialized , and only when the parent interface is actually used (such as the constants defined in the reference interface) will be initialized.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325252725&siteId=291194637
Recommended