类加载的时机
虚拟机如何加载Class文件?
Class文件里的信息进入虚拟机会发生怎样的变化?
虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是类加载机制
类加载的时机
类从被加载到内存到卸载出内存,生命周期:
加载、连接(验证、准备、解析)、初始化、使用、卸载
初始化:
- 遇到new、getstatic、putstatic或invokestatic,若类未初始化,则触发初始化
- 使用java.lang.reflect对类进行反射调用
- 父类没有进行过初始化,先初始化父类
- 虚拟机启动时,先初始化要执行的主类
- 若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" 转载请保留原文链接及作者。