JVM study notes - class loading mechanism

  Class virtual machine loads the file into memory, and data verify Class file, parsing and conversion initialization, forming Java type can be used as a virtual machine, which is the JVM class loading mechanism, which in addition to the Class file stored in the disk file, may exist in other forms, specifically refers to a series of binary byte stream.

1, Life Cycle

  Classes from memory is loaded into the virtual machine to unload the memory, the entire life cycle: loading, verification, preparation, resolution, initialization, and the use of unloading, wherein the verification, preparation and analysis section is connected to the city. In which the load, validation, preparation, initialization and unloading must be in order to start (just the beginning), then start parsing can be used to support dynamic binding after initialization.

2, the class loading procedure

2.1 Load

   External virtual machine according to a binary stream of bytes needed to store the virtual machine in the process of the format zone, the process zone storage format defined by the virtual machine itself, and a Class object instantiated in the memory (the HotSpot Virtual Machine Class objects are not located in a but in the heap area method). In the loading phase, the virtual machine needs to be done three things:

1, to obtain such a binary byte stream is defined by a fully qualified name of the class

2, these static storage structure represented by the byte stream into run-time data structure area method

3, a representative of generating in memory java.lang.Class object of this class, as a method for accessing the various data entry areas of this class.

  Non-array-based operation of acquiring the class loading stage binary byte stream, can be used to provide the bootstrap class loader system is completed, can be customized by the user class loader is completed. For the array class by itself does not create a class loader is created directly by the Java virtual machine, but the array element type or class by the class loader to create. Array class creation process need to follow these rules:

1, component type (array remove a dimension type) if the array is a reference type, then the need to get the fully qualified name of the component class to acquire Class object, the array will be loaded on the class name space of the component type class loader It is identified (two-dimensional array?).

2, if the component type is not an array reference type, the JVM will mark the array is associated with the boot class loader.

3, visibility data type and its components consistent with the type of visibility (the same?), If the component type is not a reference type, the visibility of the array class will default to the public.

2.2 verification

  The purpose of verification is to ensure | Class byte stream of information contained in the file to meet the requirements of the current virtual machine and the virtual machine will not jeopardize their own safety. There are the following four stages:

1, the file format verification:

  Verify the byte stream for compliance with Class file format, to ensure that the input byte stream can be parsed and stored in the correct area method, such as magic number 4 bytes before the test is correct. After by the verification method for storing byte stream into the area behind the validation method based on the structure of the region.

2, the metadata test:

  Metadata information such semantic checks to ensure compliance with the Java language specification. For example, testing whether the class inherits the final modified class.

3, bytecode verification:

  The method is based on test bodies, the data flow and control flow analysis to determine the semantics of the program is legitimate, logical. For example, type conversion can not be assigned to the data type of the object is no inheritance relationship.

4, reference symbol verification:

  In the resolution phase, when the virtual machine is converted to a direct reference symbol references, triggering verification of symbolic references. Symbol reference information is verified based on other than the local (reference constant pool various symbols) of the matching check, to verify that such a class can be found according to the corresponding fully qualified name string, a reference symbol classes, methods and fields whether the current class can be accessed.

2.3 Preparation

  Allocate memory for the preparation phase is set class variables and initial phase value, in the memory area used in the method of distribution (instance variables when the object is instantiated as an object allocated on the heap). If the class variable is a constant, i.e., with the modified final static class variables and, at the preparation stage will be initialized to a constant value, such as the following value in the preparation phase 123 be assigned.

public static final int value  = 123;

Other class variables are initialized to zero value. The following variable value is 0 after the preparation phase, will be in the initial stage from the class constructor <clinit> () 123 which is assigned to.

public static int value = 123;

  Various types of zero value:

type of data Zero value type of data Zero value
char '\ U0000' float 0.0f
byte (byte)0 double 0.0d
short (short)0 boolean false
int 0 reference null
long 0L    

2.4 parsed

  Parsing stage is a virtual machine to a symbolic constant pool of reference for the process of replacing direct references. There are seven kinds of reference symbols, a class or interface, fields, methods class, interface method, type method, a method handler, call qualifier points, corresponding to Class file constant pool CONSTANT_Class_info, CONSTANT_Fieldref_info, CONSTANT_Methodref_info, CONSTANT_InterfaceMethodref_info, CONSTANT_MethodType_info, CONSTANT_MethodHandler, CONSTANT_InvokeDynamic_info7 constant type. Certain direct reference is used to locate the reference position (the position of the memory objects) in memory, it may be directly to the destination pointer, or memory layout relative offset positioning indirectly a handle, and a virtual machine implementation related. Virtual machine specification does not specify how the time-resolved phase occurs, it can be resolved according to the needs to be loaded when the class loader, or until a symbol reference only to be used to resolve before.

  When the same reference symbols multiple resolution request command invokedynamic addition, results of the first virtual machine cached parse (at runtime constant pool record direct reference, and identified as the constant state resolved) to avoid repeat resolution, whether resolution is successful only parsed once. For invokedynamic instruction, as the instruction is used to support dynamic languages, corresponding reference called "dynamic call site qualifiers", you need to wait until the program actually running to this instruction only for resolution.

2.4.1 Analytical class or interface

  Suppose the current code in which the class is D, if we want a parsed never resolve symbolic references to N direct reference of a class or interface C, requires the following steps:

1, if C is not array type, the virtual fully qualified name of the N transmitted to the D class loader to load a class, in the loading process, since the metadata validation, bytecode verification, other classes may trigger loading action, such as its parent or loading implement.

2, if C is an array type, and the element type is an array of objects, according to the type of array elements loaded rules 1, and then generates an array of objects by the virtual machine and the dimensions of this array of elements representative.

3, after completion of Step C above, the virtual machine has actually become a valid class or interface, then verification of symbolic references, D verify whether they have access to the C.

2.4.2 field parsing

  Parsing a field is not parsed symbol references, need to resolve symbolic class or interface reference field belongs, or assumed by the interface belongs to the class represented by C, and then carried out successfully resolved the steps of:

1, if C itself contains a simple field names and field descriptors are matched with the target, it returns a direct reference to this field, to find the end.

2. Otherwise, if C implements the interface, according to the inheritance from the bottom up recursive search each interface and its parent interfaces, see the interface contains a simple field names and field descriptors match.

3. Otherwise, if C is not a java.lang.Object, in accordance with the inheritance from the parent class search upwards.

4, otherwise, the lookup fails.

  If found return a direct reference, the permissions verification. If the field of the same name also appear in the C interface or the parent class, or appear in both the interface and its own parent class, the compiler will complain.

2.4.3 class analytical method

  Analytical methods class class method need to resolve symbolic references relevant to the class or interface, it is assumed that a class or interface is represented by C, a method of searching for the class resolution succeeds:

1, if C is an interface, an exception is thrown.

2, to find whether there is in category C simple name and descriptor matching, if there is a direct reference to returns to this method, search ends.

3, otherwise, the parent class lunch Class C recursive lookup.

4. Otherwise, the recursive search in the list of interfaces and class C implementation of their parent interface, if the search is successful, indicating that the class C is an abstract class, an exception is thrown java.lang.AbstractMethodError.

5. Otherwise, the lookup fails.

  If found return a direct reference, to verify permissions.

2.4.4 Interface method resolution

  To parse the class or interface method reference symbol belongs, if successfully resolved, it is assumed that a class or interface is represented by C, the search interface method:

1, if C is a class rather than an interface, an exception is thrown.

2, otherwise, look in C interfaces whether there are simple name and descriptors are matched, if there is a direct reference to the return of this method, find the end.

3, otherwise, look in the parent interface recursive interface.

4, otherwise, the lookup fails.

  All interface methods are public, there is no access problem.

2.5 Initialization

  In front of the class load, in addition to custom loader participation, its operation is completely dominated by the virtual machine applications and control loading stage. Really began to execute Java code classes defined in the initialization phase. Virtual Machine Specification strict rules and only five cases of the class must be initialized (loading, validation, preparation naturally before).

1, encounter new, getstatic, putstatic invokestatic or 4 when this bytecode instruction, if the class is not been initialized, the initialization needs to be triggered. Generating the four instruction common scenario is: using the new keyword to instantiate an object, class read or set of static fields (i.e., except for the final modified compiler into the constant pool of the result), a class static method call.

When 2, java.lang.refect package using a method based on the reflecting call, if the class is not been initialized, it is necessary to initialize the flip-flop.

3, when a class is initialized, if the parent class has not been found initialization, you need to trigger initialization of the parent class.

4, when the virtual machine is started, users need to specify a main class to be executed (contains main () method of that class), the virtual machine to initialize this master class.

5, when using the dynamic language support jdk1.7, if the final result of the analysis REF_getStatic a java.lang.invoke.MethodHandle example, REF_putStatic, the method handle REF_invokeStatic, this method handle class corresponding not been initialized, it is necessary to triggers its initialization.

  In addition to these five kinds of scenes, the remaining passive references will not trigger initialization. For example, to call the parent class initialization of static fields do not trigger subclass:

public class SuperClass {

    public static int value = 12;

    static {
        System.out.println("SuperClass init");
    }

}

public class SubClass extends SuperClass{

    static {
        System.out.println("SubClass init");
    }

}

public class Test1 {

    public static void main(String[] args) {
        System.out.println(SubClass.value);
    }

}

  This code will only output "SuperClass init" and not lose "SubClass init".

  The following code is not output "SuperClass init" after the operation, which does not trigger initialization described, but triggers additional code called a "[Lcom.yue.main.SuperClass" (com.yue.main package is SuperClass initialization name) class. The automatically generated by a virtual machine, direct subclasses of java.lang.Object, for user code is not legal class name, this class represents the element type is a one-dimensional array of com.yue.main.SuperClass.

public class Test1 {

    public static void main(String[] args) {
        SuperClass[] arr = new SuperClass[2];
    }

}

  Initialization phase is performed during the class constructor <clinit> () method. Note the following aspects:

1, <clinit> () method is an assignment statement blocks and static action statement merger collected automatically by the compiler class for all class variables, whose order is determined by the statement in the source code sequence. Static statements can only access the block to define variables before the static block of statements, as defined in the variable assignment only after it can not be accessed. Variable try to write in front of the class, fewer things Sao operation.

public  class Test1 { 

    static { 
        I = 0; // normal compilation 
        System.out.println (I); // compilation fails 
    } 

    static  int I =. 1 ; 

}

2, except <clinit> () method and a class instance constructor <init> () method, no explicit call the parent class constructor.

3, the parent class <clinit> () method is executed first, the class <clinit> first executed () method must be java.lang.Object, and therefore a static block of statements in the parent class variable priority subclass assignment.

4, <clinit> () method for the class or interface is not necessary, if the class is not a static block of statements nor class variable assignment, the compiler may not be generated for the class <clinit> () method.

5, the interface can not use static statement block, but also generates <clinit> () method. Implements the interface <clinit> () method does not need to run a parent interface <clinit> () method, the interface implementation class initialization will not be performed when the <clinit> () interface method, the parent only variable defined in the interface In use, the parent interface will initialize (interface is not only constant you?).

6, the virtual guarantee of a class <clinit> () method is properly locked in a multi-threaded environment, synchronization. Therefore, only one thread to perform this type of <clinit> () method, other threads will be blocked.

3, the class loader

  Class loading phase "to get the description of such binary byte stream through a fully qualified class name of" action is achieved outside the JVM, to achieve this operation code module called a "class loader."

  For any category, you need to load it established by the class loader and the class itself with its uniqueness in the Java virtual machine, each class loader has a separate class namespace.

3.1 class loader type

  From the perspective of the Java virtual machine, class loader class can be divided into two kinds of boot loader (Bootstrap ClassLoader) and other class loader, boot class loader is part of the virtual machine itself, while the other class loader is implemented by the Java language, all derived from the abstract class java.lang.ClassLoader. From the perspective of a developer, the system provides a class loader can be divided into three kinds:

1. Start class loader:

  The class loader is responsible in <JAVA_HOME> \ lib directory and the virtual machine is recognized (identified only as a file name, such as rt.jar) library is loaded into the virtual machine memory. Start class loader can not be directly referenced Java programs.

2, the extension class loader:

  This class loader is responsible for loading <JAVA_HOME> \ lib \ ext directory, or by all libraries, developers java.ext.dirs system variables specified path can be used directly extend the class loader.

3, application class loader:

  The class loader is the return value of getSystemClassLoader ClassLoader () method, it is also referred to as a system class loader. It is responsible for loading specified on ClassPath library, the program is the default class loader.

3.2 parent delegation model

  In addition to the parent delegation model requires top-level boot loader class, the rest of the class loader should have its own parent class loader. This parent-child relationship between the class loader is not implemented in the inheritance, but by a combination relationship loader code multiplexed with the parent. Parent delegation model as shown below:

  Parent delegation model is working process: If a class loader loads the class received a request, it will put this request to delegate to the parent class loader is complete, since all loading request will be sent to the top of the boot class loader, if Search parent loader does not find the desired category, sub-loader to load just try it yourself.

  使用双亲委派模型的其中一个好处是Java类随类加载器一起具备了一种带有优先级的层次关系。比如java.lang.Object类由启动类加载器加载,因此其他所有的类使用的都会是同一个Object类。

3.3 破坏双亲委派模型

  双亲委派模型并不是强制性的约束模型,有几种大规模的非双亲委派模型情况:

1、双亲委派模型很好的解决了各个类加载器的基础类统一问题,但如果基础类又要调用回用户的代码,Java设计团队引入了线程上下文类加载器。这个类加载器可以通过java.lang.Thread类的setContextClassLoaser()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过,那这个类加载器默认就是应用程序类加载器。

Guess you like

Origin www.cnblogs.com/liuwy/p/11093923.html