类加载的时机

  1. 类加载的时机

虚拟机如何加载Class文件?
Class文件里的信息进入虚拟机会发生怎样的变化?

虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是类加载机制

类加载的时机

类从被加载到内存到卸载出内存,生命周期:
加载、连接(验证、准备、解析)、初始化、使用、卸载

初始化:

  1. 遇到new、getstatic、putstatic或invokestatic,若类未初始化,则触发初始化
  2. 使用java.lang.reflect对类进行反射调用
  3. 父类没有进行过初始化,先初始化父类
  4. 虚拟机启动时,先初始化要执行的主类
  5. 若java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic的句柄,若此方法句柄对应的类没有进行过初始化,则要先初始化。

下面以代码来演示

//父类superClass
    public class SuperClass {
        static {
            System.out.println("SuperClass init!");
        }
    public static int sup = 1111111;
    }
//子类subClass
    public class subClass extends SuperClass{
        static {
            System.out.println("SubClass init!");
        }
        public static int sub = 2222222;
    }

guess结果是啥?

分析,参考上面规则的第三条: 3. 父类没有进行过初始化,先初始化父类

首先是subClass.sub:要调用子类中的静态变量sub,那就要初始化子类,但是在子类初始化之前,还要去先初始化父类,最后才打印sub的值

在运行第二句时,两个类已经经过初始化,那么直接打印值即可。

public static void main(String[] args) {
    SuperClass[] sca = new SuperClass[10];
}

这样,并没有输出superClass init!
它代表了元素类型为superClass的一维数组,它是继承于java.lang.Object的子类

public class ConstClass {
    static{
        System.out.println("ConstClass init!");
    }    
    public static final String Hello = "Hello!";
}

public class NotInitialization {
    public static void main(String[] args) {
        System.out.println(ConstClass.Hello);
    }
}

输出什么?

Hello!!

为啥没有执行static里面的语句呢???

这里用了final,即Hello是常量,它被存放在常量池中,和ConstClass这个类没有了联系,主函数在执行时,不需要对ConstClass类进行初始化,所以最终只打印“ Hello!”


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2470290795@qq.com

文章标题:类加载的时机

文章字数:554

本文作者:runze

发布时间:2020-01-28, 14:45:07

最后更新:2020-01-28, 19:27:02

原始链接:http://yoursite.com/2020/01/28/JVM/JVM%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%9C%BA%E5%88%B61%E2%80%94%E2%80%94%E7%B1%BB%E5%8A%A0%E8%BD%BD%E7%9A%84%E6%97%B6%E6%9C%BA/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏