Java虚拟机类加载过程

来源:互联网 发布:丁克 知乎 编辑:程序博客网 时间:2024/05/21 19:41

类从加载到内存中到卸载出内存为止,整个生命周期分为:

加载

VM将通过全限定名(包名+类名)获取此类的二进制流,并将类的静态数据结构转化为方法区的运行时结构。最后会在堆中生成一个这个类的Class对象。

VM对类的二进制流的获取方式并不关心,所以可以通过网络、zip包等其他方式获取。如果我们想使用自己实现的方式来加载类的话,我们需要实现一个自定义类加载器。

验证

检查字节流是否符合VM的要求,并且不会危害VM的自身安全。
因为Class文件并不只是通过Java源文件编译而来,那么通过其他方式(甚至是直接用十六进制编辑器直接编写Class文件)可以让代码跳转到不存在的代码行上。如果不去检查,那么可能会导致VM崩溃。

准备

该阶段会为类变量分配内存并设置初始值。
内存指的事方法区。
初始值指的是,如果一个静态变量定义如下:

public static int value = 11;

那么变量的值为0。这是因为在准备阶段还没有开始执行任何Java方法,而是把value = 11的putstatic指令存放在了”clinit”方法中,该方法会在初始化阶段执行。
但如果value又是final的话,那么在此阶段,value的值就是11了。

解析

这个一个将常量池内的符号引用替换为直接引用的过程。

初始化

JVM严格地规定有且只有四种情况必须对类进行初始化:
1. 遇到new、getstatic、putstatic或invokestatic这四条指令时,如果类没有进行初始化,则需要先触发初始化。
“new”代表用new关键字创建对象。
“getstatic”、“putstatic”代表读取或设置一个非final的static字段,因为final static修饰的字段已在编译器就放入常量池了。
“invokestatic”代表调用静态方法。
2. 使用反射的时候,如果没有初始化则需要先初始化。
3. 当初始化一个类时,如果发现其父类没有初始化,则需要先初始化父类。
4. 当JVM启动时,会先初始化主类(含有main()方法的类)

其他情况如子类引用父类静态字段、初始化数组、引用常量等都不会触发父类、数组类型、类的初始化。

初始化阶段也可以看作执行类构造器”clinit”方法的过程。
1. “clinit”是由编译器自动收集类中所有类变量的赋值操作和静态语句块中的语句合并产生的。收集的顺序是按照语句在源文件中出现的顺序,所以静态语句块中只能访问定义在静态语句块之前的变量。
2. “clinit”与类的构造函数不同,它不需要显示地调用父类的构造函数。VM会保证在执行子类的”clinit”之前,完成父类”clinit”的执行。
3. “clinit”不是必须的,如果一个类中没有静态语句块,也没有对类变量的赋值操作,那么编译器可以不为这个类生成”clinit”方法。
4. 接口虽然不能使用静态语句块,但是仍然有变量初始化的赋值操作。接口与类不同,执行接口的”clinit”不需要限制性父接口的”clinit”。只有当父接口中定义的变量被使用时,父接口才会被初始化。接口的实现类在初始化时也一样不会执行接口的”clinit”。
5. VM会保证一个类的”clinit”方法在多线程中被正确地加锁和同步,如果多个线程同时去初始化一个类,那么只有一个线程会执行这个类的”clinit”方法,其他线程都需要阻塞等待,直到”clinit”执行完毕。

使用

卸载

Tips

  1. 验证、准备、解析三个部分统称为连接阶段。

  2. 加载、验证、准备、初始化、卸载的顺序是确定的,JVM会按照这个顺序开始,但不代表会等待上一阶段完成之后再进行下一阶段。这些阶段通常是互相交叉地混合式进行的。

  3. 几个阶段中,解析阶段的顺序是不确定的。它在某些情况下可以在初始化阶段之后在开始,例如动态绑定。

  4. “clinic”方法的线程安全性就是一种单例模式写法的基本原理。这种写法叫做”延迟初始化占位类模式”,代码如下:

 public class Singleton {     private static class SingletonHolder {          public static Singleton instance = new Singleton();     }     public static Singleton getInstance() {          return SingletonHolder.instance;     }     private Singleton() {     }}

以上均整理自《深入理解Java虚拟机——JVM特性及最佳实践》,一本帮你很好地理解JVM工作机制的书。

0 0
原创粉丝点击