阅读 133

JVM之虚拟机类加载时机

概述

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

Java语言中,类型的加载连接初始化都是在程序运行期间完成的,这会增加一些额外的性能开销,不过这也给Java带来了极大的扩展性和灵活性

类的加载时机

一个类的生命周期主要为:加载->验证->准备->解析->初始化->使用->卸载 这七个阶段,其中验证准备解析这三个阶段有被称为连接阶段。发生的顺序如下图:

image.png

其中解析阶段有可能在初始化阶段之后开始(参考java的运行时绑定这一性质)。

主动引用

类加载的时机只有以下六种情况:

  1. 遇见new、getstatic、putstatic以及invokestatic这四条字节码指令时候,如果类型没有初始化则需要先进行初始化。

  2. 对类型进行反射调用的时候如果类型没有被初始化,则需要先进行初始化。

  3. 初始化类的时候,其父类没有被初始化,则先初始化其父类。

  4. 虚拟机启动的时候,虚拟机会先初始化主类(包含main()方法的那个类)。

  5. 使用jdk7的动态语言支持时,一个java.lang.invoke.MethodHandle实例最后解析的结果为REF_getStaticREF_putStaticREF_invokeStaticREF_newInvokeSpecial四种类型的方法句柄,如果这个句柄的类没有被初始化则先触发初始化。

  6. 一个接口定义了JDK8新加入的默认方法(被default关键字修饰的接口方法),在初始化该接口的实现类的时候,需要先初始化该接口。

被动引用

刚刚介绍的六种情况被称为主动引用,而除此之外所有引用类型的方式都不会触发初始化,而这些则被称为被动引用。

例如:

  • 子类引用父类静态字段不会导致子类初始化。

  • 通过数组来定义引用类不会触发此类的初始化。

  • 常量在编译阶段会存入调用类的常量池,本质上没有直接引用到定义常量的类,所以不会触发初始化。

在这插入一点小知识:常量和类以及静态变量是存储在方法区中,而实例对象则是被存储在Java堆中。的话存放了基本变量类型引用对象的变量

关于接口初始化,其在初始化的时候和类的初始化不同,其并不需要父接口的初始化,只有真正用到了父接口的时候才会初始化


作者:是xiuxi休息啊
链接:https://juejin.cn/post/7032903220238385165

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐