JVM class loading mechanism - class life cycle

JVM class loading mechanism - class life cycle

What is the class loading mechanism?

The virtual machine data file that describes the classes (byte code) is loaded into memory, and data verification, preparation, resolution, and class initialization, ultimately java type (java.lang.Class objects) may be directly used in the virtual machine, this is the class loading mechanism java virtual machine. - "in-depth understanding of java virtual machine"

Class life cycle

Class is loaded into memory from the beginning until the memory is unloaded out of date, the life cycle include a class loading, verification, preparation, resolution, initialization, and unloading using 7 process, wherein the verification, preparation, parsing three processes are collectively referred to as a link.

This process will begin 7 in order, but do not need to wait until the next end of the previous process can begin a process to run, in fact, they are usually mixed with cross-cutting operation.

In Java, class loading and linking process is completed during the program run. In addition, Java can dynamically extensible language feature is dependent on dynamic loading during operation, Dynamic Link this feature implemented.

Next we learn more about the entire life cycle of the next class

A loading (loading)

In the loading phase, the virtual machine to complete three things:

  1. To obtain such a binary byte stream defined by the fully qualified name of a class.

    In addition to obtaining a binary byte stream file from the Class, you can also get from what areas?

    从ZIP或jar包中读取
    从网络中获取
    运行时计算生成(Java动态代理技术)
    由其他文件生成(由JSP文件生成对应的Class类)
    从数据库中读取
    复制代码
  2. Plus binary byte stream is stored in the method area (storage format according to the desired virtual machine).

  3. Generating in memory represents java.lang.Class object of this class, as a method for accessing the various data entry areas of this class. Class object is rather special, stored in the method area (HotSpot Virtual Machine)

Second, verify

The purpose of verification is to ensure that the information byte stream file included in Class meet the requirements of the current virtual machine and the virtual machine will not jeopardize their own safety. Generally include two aspects:

  1. Format semantics check:
    例如:
    1.是否以0xCAFEBASE开头
    2.主、次版本号是否在当前虚拟机处理范围内
    复制代码
  2. Code check logic

Third, prepare

Preparation phase officially assigned as a static variable memory and set the initial value, these static variables to allocate memory in the method area.

note:

  1. Preparation phase, JVM will allocate memory for static variables (static modification), does not include the instance variables, instance variables will be assigned along with the object when the object is instantiated in the Java heap.

    准备阶段,只会为value分配内存,不会为name分配内存
    public static int value = 123;
    private String name = "Tom";
    复制代码
  2. Set initial value:

  • modified static variables (not final): a value of zero or null

Preparation phase, not performing any Java method, and the value assigned to instruction 123 the program is compiled, stored in the class constructor method, will be performed at the initialization stage, the preparation phase, will set the value of zero.

准备阶段,会设置零值
public static int value = 123;
复制代码
  • static final modification of the constants: the actual value
常量,准备阶段会设置实际值123
public static final int value = 123;
复制代码

Note: generating at compile javac ConstantValue attributes when static final modified basic data types or String, directly assigns the value of the field ConstantValue classloading preparation phase. It can be understood as the result at compile time that is put into the constant pool. Therefore, when the class is called class A B static final field (basic data types or String), does not trigger load class B.

Fourth, resolve

The resolution phase is a virtual machine references symbolic constant pool referenced directly into the process (after the initialization phase may begin in some cases) analysis operation for the main reference class or interface, a field, a class method, four symbols interface method for, respectively, corresponding to the constant pool of the CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_infofour kinds of constant type.

1, parses the class or interface : determining a desired direct reference is converted into an array type, or the ordinary type of a reference object so as to perform different analysis.

2, field resolved : When a field is parsed, will first of this kind in the Find field contains simple name and field descriptors are matched to the goal, if so, to find the end; if not, it will follow inheritance recursive search each interface implemented by the class and their parent interface, yet, according to recursively search the parent class inheritance, until the search ends.

3, class analytical method : Analytical method class field and the step of parsing the search, only in the determination of the multi-class or method step in which the interface, and the class matching search method, the search is the first parent class, then search interface.

4, the interface analytical method : method-based analysis step and the like, but the interface does not have a parent, and therefore, only the parent interface recursive search direction on the line.

Look at the following example:

class Super{
	public static int m = 11;
	static{
		System.out.println("执行了super类静态语句块");
	}
}
 
class Father extends Super{
	public static int m = 33;
	static{
		System.out.println("执行了父类静态语句块");
	}
}
 
class Child extends Father{
	static{
		System.out.println("执行了子类静态语句块");
	}
}
 
public class StaticTest{
	public static void main(String[] args){
		System.out.println(Child.m);
	}
}
复制代码

Output:

执行了super类静态语句块
执行了父类静态语句块
33
复制代码

Why does not perform as static block subclass?

static块是在初始化阶段执行的,而static变量发生在静态解析阶段,也即是初始化之前,此时已经将字段的符号引用转化为了内存引用,也便将它与对应的类关联在了一起,由于在子类中没有查找到与m相匹配的字段,那么m便不会与子类关联在一起,因此并不会触发子类的初始化。
复制代码

Similarly, if the line commented Father class definition for m, the output results are as follows:

执行了super类静态语句块
11
复制代码

V. initialization

The final step is to initialize the class loading process, to this stage, really began to execute Java code in the class definition. During the preparation phase, class variables had been assigned an initial value once the system requirements, and in the initialization phase, is to initialize class variables and other resources in accordance with procedures specified by the programmer subjective plan , or can be expressed from another point of view: initialization phase is performed class constructor <clinit>()process approach.

Here simple instructions rules () method:

  1. <clinit>()The method is an assignment operation of the compiler automatically collected class all class variables and static statements statement in the block merger sequentially compiler collected by the statement in the order they appear in the source file of the decision , the static statement block only access to the static variables defined in a block of statements before, as defined in the variable after it, in front of a static statement can be assigned, but can not be accessed .

  2. <clinit>()The method of Example constructor <init>()method (class constructor) different, it does not explicitly call parent class constructor, virtual machine to ensure that the subclass <clinit>()before performing the method, the parent class's <clinit>()methods have been completed. Therefore, in a virtual machine the first to be executed <clinit>()class method must be java.lang.Object .

  3. <clinit>()A method for a class or interface is not necessary, if a class is not a static block of statements, there is no assignment of class variables, the compiler may not be generated for the class <clinit>()method.

  4. Interface block static statements can not be used, but there is still a class variable (final static) initializing the assignment, and therefore generate the same class interface <clinit>()methods. However, the interface is different from the class: the implementation of the interface <clinit>()does not require to execute the parent interface <clinit>()method, only when the parent variable defined in the interface is used, will be initialized parent interface . Further, the interface implementation class that implements the interface is not the same when initialization <clinit>()method.

  5. Virtual opportunity to ensure a class <clinit>()method is properly locked and synchronized in a multithreaded environment , if multiple threads to initialize a class, then there will only be one thread to perform this type of <clinit>()method, other threads are blocked need to wait, until the active thread execution <clinit>()method is completed. If a class <clinit>()has a long operating time-consuming process, it may result in multiple threads blocked in the practical application of this blockage is often very subtle.

A simple example is given below to more clearly illustrate the above rules:

class Father{
	public static int a = 1;
	static{
		a = 2;
	}
}
 
class Child extends Father{
	public static int b = a;
}
 
public class ClinitTest{
	public static void main(String[] args){
		System.out.println(Child.b);
	}
}
复制代码

Output:

2
复制代码

After the run the code look steps of:

  1. Preparation phase: allocate memory for the class variables and class variables set the initial value, so that a and b are assigned default values ​​0
  2. Initialization phase: And then the call <clinit>()when they are assigned a value to the method specified in the program
    我们调用Child.b时,触发Child的<clinit>()方法,根据规则2,在此之前,要先执行完其父类Father的<clinit>()方法,
    又根据规则1,在执行<clinit>()方法时,需要按static语句或static变量赋值操作等在代码中出现的顺序来执行相关的
    static语句,因此当触发执行Father的<clinit>()方法时,会先将a赋值为1,再执行static语句块中语句,将a赋值为2,
    而后再执行Child类的<clinit>()方法,这样便会将b的赋值为2.
    
    如果我们颠倒一下Father类中“public static int a = 1;”语句和“static语句块”的顺序,程序执行后,则会打印出1。
    很明显是根据规则1,执行Father的<clinit>()方法时,根据顺序先执行了static语句块中的内容,
    后执行了“public static int a = 1;”语句。
    另外,在颠倒二者的顺序之后,如果在static语句块中对a进行访问(比如将a赋给某个变量),
    在编译时将会报错,因为根据规则1,它只能对a进行赋值,而不能访问。
    
    复制代码

Sixth, use

Use phase includes active and passive cited references, cited the initiative will cause class initialization, and the passive reference does not cause class initialization.

Active references

jvm have strict rules, if and only if the following five conditions, that is active references , initialization will trigger a class, in addition, all references to class methods will not trigger initialization!

  1. Encounter new, getstatic, putstatic, when these four invokestatic bytecode instruction, if not the class is initialized, then immediately subjected to initialization. In fact, three cases: when a new instance of a class, or when reading a static field to the class (not including the final modified static fields, because they had been stuffed into a constant pool), as well as when performing a static method .

  2. When using java.lang.reflect. * Approach to reflect the class called, if the class has not been initialized immediately be.

  3. Initialize a class, if his father has not been initialized, initialize it to go to his father.

  4. When jvm starts, the user needs to specify a main class to be executed (containing static void main (String [] args) that category), the jvm will go to initialize the class.

  5. With Class.forName (String className); time to load classes, initializing operation is also performed.

    • Note: ClassLoader of loadClass (String className); method will load and compile a class, and its implementation will not be initialized.

Passive reference

  • Static field references the parent class, would lead to initialize the parent class, without causing initialize the subclass.
  • Defined array of classes, it does not cause class initialization.
  • static final constant reference to the class, will not cause class initialization (if only static modification, or will cause class initialization).

Passive reference sample code:

class InitClass{
	static {
		System.out.println("初始化InitClass");
	}
	public static String a = null;
	public final static String b = "b";
	public static void method(){}
}
 
class SubInitClass extends InitClass{
	static {
		System.out.println("初始化SubInitClass");
	}
}
 
public class Test4 {
 
	public static void main(String[] args) throws Exception{
	//	String a = SubInitClass.a;// 引用父类的静态字段,只会引起父类初始化,而不会引起子类的初始化
	//	String b = InitClass.b;// 使用类的final常量不会引起类的初始化
		SubInitClass[] sc = new SubInitClass[10];// 定义类数组不会引起类的初始化
	}
}
复制代码

When the use phase is complete, java class entered the unloading phase.

Seven, uninstall

After completion of the use of the class, if the following conditions is true class is unloaded:

  • All instances of the class have been recovered, that is java heap any instance of the class does not exist.
  • Load class ClassLoader has been recovered.
  • Java.lang.Class corresponding to the class object is not referenced anywhere, not reflected by the method of accessing the class anywhere.

If the above three conditions are satisfied, jvm class will be unloaded when garbage collection methods district, the uninstall process is actually kind of cleared area in the method class information, java classes throughout the life cycle is over.

to sum up

Entire class loading process, in addition to the user application can define the class loader from outside involvement, all the remaining actions in the virtual machine completely dominated by the loading stage and control. To begin the initialization program code to execute Java (and also bytecode) defined in the class, but this is just the beginning of code execution, which is limited to <clinit>()the method. Class loading process is mainly the Class file (to be exact, it should be the class of binary byte stream) loaded into the virtual machine memory, actually perform the operation bytecode, really began only after loading is complete.

Reference material

[Java Virtual Machine] depth of four: the class loading mechanism

The JVM class loading mechanism

Guess you like

Origin juejin.im/post/5d634864e51d4561ee1bdf8c