虚拟机类加载机制

虚拟机类加载机制

@(Java虚拟机)[类加载]

[TOC]

类加载时机

类加载到卸载的生命周期包括:

  • 加载(Loading)
  • 验证(Verification)
  • 准备(Preparation)
  • 解析(Resolution)
  • 初始化(Initialization)
  • 使用(Using)
  • 卸载(Unloading)
虚拟机类加载机制_第1张图片
类的生命周期

其它阶段按步执行,但解析阶段不一定在初始化后。可能在初始化之后或者交差。为的是支持Java语言的运行时绑定(动态绑定或晚期绑定)。

对类的第一个阶段:加载,虚拟机没有强制约束,但是对于初始化阶段,虚拟机规定了有且仅有5种情况必须立即对类进行"初始化"。其他过程在此之前。

  1. 遇到new,getstatic,putstatic或invokestatic字节码指令时,如果类没有初始化则必须先初始化。4个指令最常见的场景是:使用new关键字实例化对象的时候,读取或设置一个类的静态字段(被final修饰,已在编译器把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。
  2. 使用reflect包的方法对类进行反射调用的时候,没有初始化则先初始化。
  3. 初始化类时发现其父类还没有进行初始化。
  4. 虚拟机启动时,用户需指定一个要执行的主类(main()),虚拟机先初始化这个类。
  5. 当使用jdk1.7的动态语言支持时,如果MethodHandle实例最后解析结果REF_getStatic,REF_putStatic,REF_invokeStatic的方法句柄,并且这个方法的句柄对应的类没有初始化。

这5种行为称为对一个类进行主动引用。被动引用举例:

public class Test2 {
    public static void main(String[] args) throws InterruptedException {
        //1.通过子类引用父类的静态字段,不会导致子类初始化。
        //输出结果为
        //SuperClass init
        //3
        System.out.println(SubClass.value);
        //2.数组定义,不会触发
        SuperClass[] subClasses=new SuperClass[10];
        //3.value如果为常量,都不会初始化
        //输出结果为
        //3
        System.out.println(SubClass.value);
    }
}

class SuperClass {
    public final static int value=3;
    public  static int value=3;
    static {
        System.out.println("SuperClass init");
    }
}
class SubClass extends SuperClass{
    static {
        System.out.println("SubClass init");
    }
}

类加载过程

加载

在加载过程中,虚拟机需要完成的:

  • 通过类的全限定名来获取定义此类的二进制字节流
  • 将这个字节流代表的静态存储结构转为方法区的运行时数据结构
  • 在内存中生成一个Class对象对应这个类。

你可能感兴趣的:(虚拟机类加载机制)