1 What is the load of a class
Class loading refers to reading the binary data in the class's. class file into memory, placing it in the method area of the run-time data area, and then creating a Java.lang.Class object in the heap that encapsulates the data structure of the class within the method area. The final product loaded by a class is a class object located in the heap, which encapsulates the data structure of the class within the method area and provides the programmer with an interface to access the data structures within the method area.
Life cycle of Class 2
Class starts from being loaded into the virtual machine's memory, and its entire lifecycle includes: Load (Loading), validate (verification), prepare (preparation), Parse (Resolution), Initialize ( initialization), use (using), and unload (unloading) 7 stages. The process of loading, validating, preparing, parsing, and initializing five stages of the class load . and prepare, verify, parse 3 parts collectively known as the Connection (linking),.
The order of the 5 stages of loading, validating, preparing, initializing, and unloading is determined, and the load process of the class must begin in this order, and the parsing phase is not necessarily: it can be started after the initialization phase in some cases, This is to support runtime bindings for the Java language (also known as dynamic binding or late binding). Also note that the stages here are started in order, rather than sequentially or in order, because these phases are usually mixed in a cross-section, often invoking or activating another phase during one phase of execution.
3 Loading
To find and load the binary data of a class, loading is the first stage in the class loading process, and during the load phase, the virtual machine needs to complete the following three things:
- Gets its defined binary byte stream through the fully qualified name of a class.
- Converts the static storage structure represented by this byte stream into the run-time data structure of the method area.
- A Java.lang.Class object representing this class is generated in the Java heap as a access entry to the data in the method area.
In contrast to other phases, the load phase (accurately, the action of getting the binary byte stream of a class during the load phase) is the most controllable phase, because the developer can either use the system-provided classloader to complete the load or customize its own classloader to complete the load.
When the load phase is complete, the binary byte stream outside the virtual machine is stored in the method area in the format required by the virtual machine, and an object of the Java.lang.Class class is created in the Java heap so that the data in the method area can be accessed through the object.
Java Virtual machines have pre-loaded functionality. The ClassLoader does not need to wait until a class is "first active" and then load it, and the JVM specification stipulates that the JVM can predict the load of a class, and if the class is wrong, but the application does not call the class, the JVM does not error, and if this class is called, the JVM will error. (linkageerror error). In fact, a word, Java Virtual machine has preloaded functionality. Class Loader
Class loaders have hierarchical relationships such as:
From the developer's point of view, the ClassLoader can be categorized into the following three categories:
- Root loader: Bootstrap ClassLoader, which is responsible for loading the jdk\jre\lib (the JDK represents the JDK's installation directory, the same below), or the path specified by the-xbootclasspath parameter, and class libraries that can be recognized by virtual machines (such as Rt.jar, all java. classes that begin with bootstrap ClassLoader are loaded). The startup ClassLoader cannot be referenced directly by a Java program.
- Extension class loader: Extclassloader, which is implemented by Sun.misc.launcher$extclassloader and is responsible for loading the Jdk\jre\lib\ext directory, or all class libraries in the path specified by the JAVA.EXT.DIRS system variable (such as javax. Class), developers can use the extension class loader directly.
- Application class Loader: Appclassloader, which is implemented by Sun.misc.launcher$appclassloader, is responsible for loading the class specified by the user classpath (ClassPath), which the developer can use directly with the ClassLoader. If you do not have your own classloader in your application, this is typically the default class loader in your program.
The root ClassLoader, which is implemented in C + +, is not visible at the Java level; Let's take a look at the Extclassloader code, which is in the Launcher class,
Static class extends URLClassLoader
At the same time we look at Appclassloader, it is also in the launcher,
Static class extends URLClassLoader
They inherit a class of URLClassLoader at the same time.
About this hierarchical relationship that looks like inheritance is actually not. We see the code above to know that Extclassloader and Appclassloader inherit the same class at the same time. At the same time we look at the ClassLoader LoadClass method can also be known, the following paste the source code:
Private FinalClassLoader parent;protectedClass<?> loadclass (String name,Booleanresolve)throwsClassNotFoundException {synchronized(Getclassloadinglock (name)) {//First , check if the class has already been loadedClass C =Findloadedclass (name); if(c = =NULL) { LongT0 =System.nanotime (); Try { if(Parent! =NULL) {C= Parent.loadclass (Name,false); } Else{C=findbootstrapclassornull (name); } } Catch(ClassNotFoundException e) {//ClassNotFoundException thrown if class not found//From the Non-null parent class loader } returnC; } }
The source code is not all posted, just stick out the key codes. From the above code we know first to check whether the class has been loaded, if it has been loaded then directly take out, otherwise loading. There is a parent property, which is a representation of the parents loader. This is exactly how the relationship between the loaders is not an inheritance relationship.
Parental delegation Model
The workflow of the parent delegation model is that if a classloader receives a request for a class load, it does not attempt to load the class on its own, but instead delegates the request to the parent loader to complete, then up, so that all class load requests should eventually be passed to the top-level startup class loader. The load cannot be completed until the parent loader finds the required class in its search scope, and the child loader tries to load the class on its own.
Parent delegation Mechanism:
- When Appclassloader loads a class, it first does not attempt to load the class itself, but instead delegates the class load request to the parent ClassLoader Extclassloader to complete.
- When Extclassloader loads a class, it does not attempt to load the class on its own, but instead delegates the class load request to Bootstrapclassloader to complete.
- If the bootstrapclassloader fails to load (for example, the class is not found in $java_home/jre/lib), the extclassloader is used to try to load;
- If the Extclassloader also fails to load, the Appclassloader will be used to load, and if the Appclassloader also fails to load, an exception classnotfoundexception will be reported.
Parental delegation Model meaning:
- System class prevents multiple copies of the same byte code in memory
- Ensure safe and stable operation of Java programs
4. Connection Verification
Validation: Ensure that the class being loaded is correct
The purpose of the verification is to ensure that the information contained in the byte stream of the class file conforms to the requirements of the current virtual machine and does not compromise the security of the virtual machine itself. The validation phase will roughly complete the 4-phase inspection action:
- File Format verification: Verify that the byte stream conforms to the specification of the class file format, for example: whether to start with 0xCAFEBABE, whether the major and minor version numbers are within the processing range of the current virtual machine, and whether the constants in the constant pool have unsupported types.
- Meta-data validation: Semantic analysis of the information described in bytecode (note: Comparing the semantic analysis of the JAVAC compilation phase) to ensure that the information it describes conforms to the requirements of the Java language specification, for example: Whether this class has a parent class, except Java.lang.Object.
- Bytecode verification: Through data flow and control flow analysis, it is reasonable to determine that the program semantics are legal and logical.
- Symbol Reference Validation: Ensures that parsing actions are performed correctly.
The validation phase is important, but not necessary, and it has no effect on the program runtime, and if the referenced classes are repeatedly validated, consider using the-xverifynone parameter to turn off most of the class validation measures to shorten the load time of the virtual machine class.
Get ready
Prepare: Allocates memory for static variables of a class and initializes it to a default value
The prep phase is a phase that formally allocates memory for class variables and sets the initial value of class variables, which are allocated in the method area. There are a few things to note about this phase:
- In this case, the memory allocation consists of only class variables (static), not instance variables, and the instance variables are allocated to the Java heap as the object is instantiated.
- The initial value set here is typically the default value of 0 for the data type (such as 0, 0L, NULL, FALSE, and so on), rather than being explicitly assigned to the value in Java code.
Suppose a class variable is defined as:
Public Static int value = 3;
Then value the initial value of the variable after the preparation phase is 0, not 3, because no Java method has been executed at this time, and the value instruction assigned to 3 is stored in the class constructor <clinit> () method after the program is compiled, so the value An assignment of 3 is performed at the initialization stage.
Analytical
Parse: Converts a symbolic reference in a class to a direct reference
The parsing phase is the process by which a virtual machine replaces a symbolic reference within a constant pool with a direct reference, and the parsing action is primarily for a class or interface, a field, a class method, an interface method, a method type, a method handle, and a call Point qualifier 7 class symbol reference. A symbolic reference is a set of symbols that describe a target, which can be any literal.
A direct reference is a pointer directly to the target, a relative offset, or a handle that is indirectly anchored to the target.
For example, the A method in Class A refers to the B method in Class B, then it finds the memory address of the B method of Class B and replaces the symbolic reference with a direct reference (memory address).
5. Initialization
initialization, which assigns the correct initial value to the static variables of the class, the JVM is responsible for initializing the class, primarily initializing the class variables.
There are two ways to set the initial value of a class variable in Java:
- Declaring a class variable is a specified initial value
- Specifying an initial value for a class variable using a static code block
JVM initialization Step (case without parent class):
1) static property of Class 2) class static code block 3) class non-static property 4) class non-static code block 5) Construction method
JVM initialization Step (case with parent class):
1) static property of parent class 2) static code block of parent class 3) static property of Subclass 4) subclass static code block 5) Non-static property of parent Class 6) non-static code block of parent class 7) Parent class construction method 8) Subclass non-static attribute 9) subclass non-static code block 10) sub-class construction method
To illustrate, static blocks and static properties are equivalent, and they are executed in code order.
Example:
Public classSingleton {Private StaticSingleton Singleton =NewSingleton (); Public Static intCounter1; Public Static intCounter2 = 0;PrivateSingleton () {Counter1++; Counter2++;} Public StaticSingleton Getsingleton () {returnSingleton;}}
Here is our test class Testsingleton
Public class Testsingleton {publicstaticvoid main (String args[]) { = Singleton.getsingleton (); System.out.println ("counter1=" +singleton.counter1); System.out.println ("counter2=" +Singleton.counter2);}}
The output is:
Counter1=1counter2=0
We analyze the steps one-by-one:
1 Execute Testsingleton The first sentence, because we do not load and connect the singleton class, so we need to load and connect it first. In the preparation phase of the connection, we assign the default initial value to the static variable.
Singleton =null=0=0
2 after the loading and the connection is complete, we will do the initialization work again. Initialization is performed from top to bottom, note that this time has not been called Singleton.getsingleton ();
The Singleton = new Singleton () is executed first, and the internal logic of the construction method is executed, and the + + is performed at this time counter1=1,counter2 = 1;
Next executes the counter1, and we do not assign a value to it, so it does not need to be initialized; at this time counter1=1,counter2 = 1;
The last execution counter2 = 0; Counter2 is assigned a value of 0, at this time counter1=1,counter2 = 0;
3 After initialization we are going to call the static method Singleton.getsingleton (); We know that the returned singleton has been initialized, so the output will take 1 and 0 for granted.
Reference:
In-depth understanding of Java class loading mechanism (i)
In-depth understanding of Java class loading mechanism (ii)
Loading mechanism of Java class
Java Virtual machine class loading mechanism
Class loading mechanism of Java Learning Note-JVM