Jvm 类加载机制

Published: by Creative Commons Licence

  • Tags:

JVM的类加载机制

java的类在javac指令编译后为class文件。JVM的类加载分为七个阶段:

  1. 加载
  2. 验证
  3. 准备
  4. 解析
  5. 初始化
  6. 使用
  7. 卸载

让我们逐一描述:

1.加载

类加载时机虚拟机规范并没有规定,自由发挥。

加载完成下列流程:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流(并没有指明要从一个Class文件中获取,可以从其他渠道,譬如:网络、动态生成、数据库等);
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
  3. 在内存中(对于HotSpot虚拟就而言就是方法区)生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;

2.验证

这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

3.准备

准备阶段是正式为类变量(static 成员变量)分配内存并设置类变量零值的阶段,这些变量所使用的内存都将在方法区中进行分配。

注意对于static final变量,其在这个阶段会直接赋予初始值。

4.解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

5.初始化

初始化发生的时机为如下五种情况:

  1. 遇到new、getstatic、putstatic或invokestatic这四条字节码指令
  2. 使用java.lang.reflect包的方法对类进行反射调用的时候
  3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  4. 虚拟机执行时的main类会在虚拟机启动时初始化
  5. 当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getstatic,REF_putstatic, REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。

初始化阶段是执行类构造器<clinit>()方法的过程。 <clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块static{}中的语句合并产生的, 编译器收集的顺序是由语句在源文件中出现的顺序所决定的。

6.使用

在类加载到类卸载的过程中我们都可以使用该类结构。

7.卸载

卸载发生在该类的.class文件不再被外部引用时,由虚拟机自发进行回收卸载。