Objective
We know that the program we wrote has been compiled into a. class file, and the. class file describes the various information of the classes, which ultimately needs to be loaded into the virtual machine before it can be run and used. And how does the virtual machine load these. class files? What happens after the information for the. class file enters the virtual machine? These are all what this article is about, and the article will explain what the Java virtual machine needs to do (bold red) in each phase of loading the load class.
7 Stages of class use
Class starts from being loaded into the virtual machine's memory and unloads out of memory, and its entire lifecycle includes: Load (Loading), validate (verification), prepare (preparation), Parse (Resolution), Initialization (initiallization), use (using), and unload (unloading) are 7 stages. Where the validation, preparation, parsing of 3 parts collectively referred to as the connection (linking), these seven stages of the order of occurrence such as:
In the diagram, the order of the 5 stages of loading, validating, preparing, initializing, and unloading is determined, and the loading process of the class must begin in this order, and the parsing phase does not have to be: it can begin after the initialization phase in some cases, which is to support runtime binding of the Java language (also known as dynamic binding). The next step is to load, validate, prepare, parse, initialize five steps, which constitute a complete class loading process. With nothing to say, uninstalling the work that belongs to the GC has been mentioned in the previous GC article.
Load loading
Loading is the first stage of a class load. There are two kinds of time-of-Chance trigger class loading:
1. Pre-load. When the virtual machine starts up, it loads the. class file under Rt.jar in the java_home/lib/, which is very often used when the program is running, such as java.lang.*, java.util.*, java.io.* and so on, so as the virtual machine loads together. To prove this is simple, write an empty main function, set the virtual machine parameter to "-xx:+traceclassloading" to get the class load information, run it:
1[Opened E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar]2[Loaded Java.lang.Object from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar]3[Loaded java.io.Serializable from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar]4[Loaded java.lang.Comparable from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar]5[Loaded java.lang.CharSequence from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar]6[Loaded java.lang.String from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar]7[Loaded java.lang.reflect.GenericDeclaration from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_ 1.6.0.013\jre\lib\rt.jar]8[Loaded Java.lang.reflect.Type from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar]9[Loaded java.lang.reflect.AnnotatedElement from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_ 1.6.0.013\jre\lib\rt.jar]Ten[Loaded Java.lang.Class from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar] One[Loaded java.lang.Cloneable from E:\MyEclipse10\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\rt.jar] A...
2. Load at runtime. When a. class file is used by a virtual machine, the. class file is checked in memory to see if it is loaded, and if not, the class is loaded by the fully qualified name of the class.
Well, what the loading phase did, actually the loading phase did have three things:
1 . Get a binary stream of the. class file
2, the class information, static variables, bytecode, constants, the contents of these. class files are placed in the method area
3 . Generate a Java.lang.Class object in memory that represents the. class file as a access entry for various data in this class of the method area. Generally this class is in the heap, but the hotspot virtual machine is very special, this class object is placed in the method area
The requirements for these three points are not specific to the virtual machine specification, so the flexibility of the virtual machine implementation and the specific application is quite large. For example, in the first article, there is no indication of where the binary stream will come from or how it should be, so this alone can produce many tricks:
· Obtained from the ZIP package, which is the basis for future jar, ear, and war formats
· Get from the network, the typical application is the applet
· Run-time compute generation, typical application is dynamic agent technology
· Generated by other files, the typical application is JSP, which is generated by the JSP corresponding. class file
· Read from database, this kind of long diameter is relatively rare
In a nutshell, this is part of the most manageable phase of a developer's process of loading the class.
Verify
The first step in the connection phase 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 Java language itself is a relatively safe language (as opposed to C + +), but as mentioned earlier, the. class file does not have to be compiled from the Java source code and can be generated in any way, even with a hexadecimal editor that is written directly to produce a. class file. At the bytecode language level, Java code can be expressed at least semantically. If the virtual machine does not check the input byte stream and fully trusts it, it is likely that the system crashes due to the loading of the harmful byte stream, so authentication is an important work for the virtual machine to protect itself.
The validation phase will do a few things, specifically, this is the virtual machine implementation level of the problem:
1. File Format Verification
This place has to say something about the developer. The. 5~ 8th byte of the. class file represents the primary and secondary version number of the. class file, which verifies that the 4 bytes are validated A higher version of the JDK can be backwards-compatible with the previous version of the. class file, but cannot run a later class file , and the virtual machine must refuse to execute a. class file that exceeds its version number, even if the file format has not changed. For example, if the Java code is compiled under JDK1.6, then the JDK1.6, JDK1.7 environment can run this. Java code-generated. class file, but JDK1.5, The lower JDK version of JDK1.4 is unable to run this. Java code generated by the. class file. If run, will throw java.lang.UnsupportedClassVersionError, this small detail, be sure to note.
2. Meta-data validation
3. Byte code Verification
4. Symbol Reference Verification
Get ready
The prep phase is a phase that formally allocates memory for class variables and sets their initial values, and the memory used by these variables is allocated in the method area . In this regard, there are two places to note:
1, when memory allocation is only a class variable (static modified variable), not an instance variable, the instance variable will be allocated in the Java heap with the object when the object is instantiated
2. Variables that assign initial values at this stage refer to static variables that are not final modified, such as "public static int value = 123;", and value is 0 instead of 123 after the prep phase. An action that assigns value 123 to value is performed during the initialization phase, such as "public static final int value = 123;" is not the same, in the preparation phase, the virtual machine will give value assigned to 123.
The 0 values for each data type are as follows:
Analytical
The parsing phase is the process by which a virtual machine replaces a symbolic reference within a constant pool with a direct reference . To see what the difference is between a symbolic reference and a direct reference:
1, the symbol reference.
This is actually the concept of the compilation principle, the symbolic reference includes the following three types of constants:
· Fully qualified names for classes and interfaces
· Name and descriptor of the field
· The name and descriptor of the method
So it might not be good to understand, with the actual look, write a very simple code:
1 PackageCom.xrq.test6;2 3 Public classTestmain4 {5 Private Static inti;6 Private DoubleD;7 8 Public Static voidprint ()9 {Ten One } A - Private BooleanTrueorfalse () - { the return false; - } -}
Use JAVAP to decompile the. Class of this code:
Constant Pool: #1 = Class #2//Com/xrq/test6/testmain#2 = Utf8 com/xrq/test6/Testmain #3 = Class #4//Java/lang/object#4 = Utf8 java/lang/Object #3 {Utf8 I #6 =Utf8 I #7 =Utf8 D #8 =Utf8 D #9 = Utf8 <init> #10 =Utf8 () V #11 =Utf8 Code #MethodRef = #3. #13//java/lang/object. " <init> ":() V#13 = Nameandtype #9: #10//"<init>":() V#14 =Utf8 linenumbertable #15 =Utf8 localvariabletable #Utf8 = This #* = Utf8 lcom/xrq/test6/Testmain; #18 =Utf8 Print #19 =Utf8 Trueorfalse #20 =Utf8 () Z #21 =Utf8 SourceFile #* = Utf8 Testmain.java
There are 22 items in the constant pool that are constant pools, with "Utf8" being the symbol reference. For example, it has a value of "Com/xrq/test6/testmain", which represents the fully qualified name of the class, and for example, the number of I, #6为I, they are a pair, the variable is the integer (int) type, the name is "I", the #6为D, #7为d也是一样, Represents a variable of type double (double) with the name D; #18, #19表示的都是方法的名字.
In fact, the symbolic reference is the same as what we said above, which is the description of the class, variable, and method. The symbolic reference is not related to the memory layout of the virtual machine, and the referenced target may not already be loaded into memory.
2. Direct reference
A direct reference can be a pointer to a target directly, a relative offset, or a handle that can be indirectly anchored to the target. The direct reference is related to the memory layout implemented by the virtual machine, and the direct references that are translated from the same symbol reference on different virtual machine samples are generally not the same. If there is a direct reference, the referenced target must already exist in memory.
Initialization
The initialization phase is the last step in the class loading process, and the initialization phase is the process of actually executing the Java program code (or bytecode) defined in the class. The initialization process is the process of executing a class constructor <clinit> () method that initializes class variables and other resources based on a subjective plan developed by the programmer through the program. To white this sentence, in fact the initialization phase is to give the static variable a user-specified value and execute a static code block .
Note that the virtual opportunity guarantees that the initialization of the class is properly locked and synchronized in a multithreaded environment , that is, if multiple threads are initializing a class at the same time, there will only be one class that executes the <clinit> () method of the class, and the other threads block the wait. Until the active thread Execution <clinit> () method is complete. Therefore, if there is a lengthy operation in the <clinit> () method of a class, it can cause multiple processes to block. However, while other threads will block, but the thread that executes the <clinit> () method exits the <clinit> () method, the other counties will not enter the <clinit> () method again, because the same classloader A class is initialized only once. In practice, this blockage is often relatively covert and should be used with caution.
The Java Virtual Machine specification strictly stipulates that there are only 5 scenarios where classes must be initialized immediately, and these 4 scenarios are called active references to a class (in fact, there is a scenario, but for the moment I do not understand the meaning of this scenario, I will not write first):
1, use the new keyword to instantiate an object, read or set a static field of a class (except for a static field that is final decorated), when invoking a static method of a class
2. When a reflection call is made to a class using the methods in the Java.lang.reflect package
3. Initializes a class and discovers that its parent class has not been initialized yet.
4, when the virtual machine starts, the virtual opportunity first initializes the user-specified class that contains the main () method
In addition to the above 4 scenarios, all methods of referencing a class do not trigger the initialization of the class, called the passive reference, followed by a few examples of passive references:
1. Subclasses refer to the parent class static fields and do not cause subclasses to initialize. As to whether the subclass is loaded and validated, the former can be viewed by "-xx:+traceclassloading"
Public classsuperclass{ Public Static intValue = 123; Static{System.out.println ("Superclass Init"); }} Public classSubclassextendssuperclass{Static{System.out.println ("Subclass Init"); }} Public classtestmain{ Public Static voidMain (string[] args) {System.out.println (subclass.value); }}
Run the result as
Superclass Init123
2. Referencing a class through an array definition does not trigger initialization of this class
Public class superclass{ publicstaticint value = 123; Static { System.out.println ("superclass init");} } Public class testmain{ publicstaticvoid main (string[] args) { New Superclass[10];} }
Run the result as
3, when a static constant is referenced, the constants are stored in the class's constant pool at compile time and are not directly referenced to the class that defines the constants.
Public class constclass{ publicstaticfinal String HELLOWORLD = "Hello world"; static { System.out.println ("Constclass init");} } Public class testmain{ publicstaticvoid main (string[] args) { System.out.println (Constclass.helloworld); }}
Run the result as
Hello World
In the compile phase through constant propagation optimization, the value of the constant HelloWorld "Hello world" is actually stored in the constant pool of the Notinitialization class, Subsequent notinitialization of the constant Constclass.helloworld are actually converted to the Notinitialization class's reference to its own constant pool. In other words, the actual notinitialization class file does not have a constclass of the symbol reference entry, and these two classes do not have any connection after being translated into class.
Java Virtual machine Learning 9, Java class loading mechanism