前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java虚拟机--类加载的时机

Java虚拟机--类加载的时机

作者头像
SuperHeroes
发布2018-05-22 16:27:11
4460
发布2018-05-22 16:27:11
举报
文章被收录于专栏:云霄雨霁

类加载时机:

类从被加载到内存中开始,到卸载出内存为止,要经历7个阶段:

加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,类加载过程中必须按照这种顺序按部就班的开始(注意是“开始”,而不是“完成”,因为这些阶段通常是交叉进行的),而解析阶段不确定,解析阶段可以在初始化之前或之后进行,这也正是Java支持动态绑定的原因。

什么情况下需要开始类加载的第一个阶段----加载,Java虚拟机没有强制约束,但Java虚拟机强制约束了类的初始化的开始时间(而加载、验证、准备自然在初始化之前进行),有且只有以下5种情况对类进行初始化:

  1. 遇到new、getstatic、putstatic、invokestatic四个字节码命令时。这四条指令最常见的Java代码是:使用new关键字实例化对象、读取或设置一个类的静态字段、调用一个类的静态方法。
  2. 使用java.lang.reflect包的方法对类进行反射调用时。
  3. 当初始化一个类时,如果其父类还没有初始化,则需要先初始化父类。
  4. 虚拟机启动时,虚拟机会先初始化主类(含有main()的哪个类)。
  5. 当使用动态语言支持时(JDK1.7以上),如果一个Java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄对应的类没有初始化,需要先初始化。

这5种场景中的行为称为对一个类的主动引用。除此以外,所有引用类的方式都不会出发初始化,称为被动引用。下面是三种被动引用的例子:

1、对于静态字段,只有直接定义这个字段的类才会被初始化。因此通过子类引用父类中定义的静态字段,只会触发父类初始化。

可以看出,并没有输出“SubClass",说明SubClass没有被初始化。

2、创建一个类的数组,不会触发该类的初始化。

可以看出,没有任何输出,说明SuperClass没有被初始化。

3、引用一个类的常量,不会触发该类的初始化。

可以看出,没有输出”ConstClass“,说明ConstClass没有被初始化。

接口的初始化:

接口的加载过程与类的加载过程稍微有一点不同:接口也有初始化过程,这点和类一样。接口和类的区别在与5种场景的第三种:当一个类初始化时,要求其父类都初始化了,但一个接口初始化时,并不要求父接口初始化,只有在真正使用到父接口时才进行初始化。

下一篇:Java虚拟机--类加载过程

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类加载时机:
    • 1、对于静态字段,只有直接定义这个字段的类才会被初始化。因此通过子类引用父类中定义的静态字段,只会触发父类初始化。
      • 2、创建一个类的数组,不会触发该类的初始化。
        • 3、引用一个类的常量,不会触发该类的初始化。
        • 接口的初始化:
        • 下一篇:Java虚拟机--类加载过程
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档