虚拟机加载时机

类从加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:
加载的生命周期

从这个图中可以看出,虚拟机的加载顺序,其中加载,验证,准备,初始化和卸载的顺序的确定的,类的加载过程必须按照这个顺序开始,而解析就不一定。他可能在初始化阶段之后再开始,这是为了支持Java语言的运行时动态绑定设计的。

那什么情况下需要进行类的加载呢?Java虚拟机并没有进行强制的规定。在虚拟机规范中对于类强制初始化有5种情况(而加载,验证,准备自然都在此阶段之前开始),那么哪几种情况需要主动初始化呢?

a:遇到new,getstatic,putstatic,invokestatic这4个指令的时候,如果类还没有经过初始化,则需要触发类的初始化操作。生成这4个指令的常见场景是:使用new关键字实例化一个对象,读取或者设置一个静态的字段以及调用一个类的静态方法的时候。

b:使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有初始化,就先触发其初始化。

c:当初始化一个类的时候,如果发现其父类没有初始化的时候,先初始化其父类。

d:当虚拟机启动的时候,用户需要一个指定的执行的方法(java中是Main方法),虚拟机先初始化这个类。

e:当使用JDK1.7的时候,如果java.lang.invoke.MethodHandle实例的解析结果是REF_getStatic, REF_pusStatic,REF_invokeStatic的方法句柄,并且这个句柄的类没有被初始化,则需要先初始化这个类。

对于以上的5中触发类的初始化的场景,虚拟机规范中有一个强烈的限定语,“有且只有”,这5中场景中的行为成为对一个类的主动引用,初次之外,所有引用类的方式都不会触发初始化,称为被动引用。下面三种方式都是类的被动引用。

a:通过子类引用父类的静态字段,不会导致子类的初始化。
这是子类和父类

这是一个main方法

这是上面的运行的结果

b:通过定义数组来引用类,不会触发类的初始化(new一个对象,会触发类的初始化)。
在控制台中没有打印出初始化的语句

c:常量在编译阶段就存入到了类的常量池中,本质上并没有直接引用到定义在常量中的类,因此也不会进行类的初始化。就是在类中定义一个public static final String name=“hello”是不会初始化这个类的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值