美文网首页
虚拟机类加载机制

虚拟机类加载机制

作者: wang_zd | 来源:发表于2019-01-08 21:15 被阅读3次

    虚拟机类加载机制

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

    [TOC]

    类加载时机

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

    • 加载(Loading)
    • 验证(Verification)
    • 准备(Preparation)
    • 解析(Resolution)
    • 初始化(Initialization)
    • 使用(Using)
    • 卸载(Unloading)
    类的生命周期

    其它阶段按步执行,但解析阶段不一定在初始化后。可能在初始化之后或者交差。为的是支持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对象对应这个类。

    相关文章

      网友评论

          本文标题:虚拟机类加载机制

          本文链接:https://www.haomeiwen.com/subject/ktrrcftx.html