Stay Hungry Stay Foolish

Java 类型的生命周期

Posted on By Jun Xi Gu

本文是对Java 类型的生命周期的汇总和个人理解


是什么?

Java的类型以class文件的形式被导入到JVM中,然后被程序使用,当不再使用时被JVM卸载

JVM规范没有规定什么时候导入class文件,但规定了JVM在 主动使用 一个类型之前必须已经完成class的导入;导入包括装载,链接和初始化 3个阶段;

以下场景属于对一个类型的主动使用

  • 创建一个类的实例
  • 调用类的静态方法
  • 使用类或接口的静态变量(非编译常量)
  • 使用Java API的某些反射方法
  • 初始化一个类的子类
  • 当虚拟机启动某个被标明为启动类的类

子类或子接口通过继承得来的静态变量只是被动使用

class的装载,链接和初始化 必须按照顺序进行,但链接中的 部分对class的验证过程会在装载中执行,链接中的解析可以延迟到初始化之后进行

装载

装载的过程是一个动态的扩展程序的过程,装载阶段需要完成3项任务

  • 通过类型的全限定名产生一个class格式的二进制流
  • 解析二进制流并在方法区中生成类型信息
  • 创建该类型的Class实例

连接

验证

对class格式的二进制流的验证部分发生在装载期间(如检查class的文件格式,长度),部分发生在解析期间(验证符号引用),除此以外,验证阶段验证的内容包括各类二进制兼容性:

  • 检查final类不能拥有子类
  • 检查final方法不能被覆盖
  • 确保在类型和超类之间不存在不兼容的方法声明
  • 检查所有常量池入口相互一致
  • 检查常量池中所有的特殊字符串
  • 检查字节码的完整性

准备

JVM为类变量分配内存并初始化为默认值

解析

对常量池中的符号引用替换为直接引用,解析的时候可能会触发新类型的装载、准备

指向类型、类变量、类方法的直接引用很可能是指向方法区的本地指针,而指向实例变量和实例方法的直接引用都是偏移

初始化

若父类未初始化受限初始化父类,然后执行类的静态初始化语句来初始化类变量的值

卸载

当一个类型的Class对象在垃圾收集时不可达 就可以触发垃圾回收(具体的回收策略由JVM的具体实现决定),当一个类的对象能可达,则垃圾回收器则通过该对象找到方法区中的类型信息,通过方法区中的Class对象引用 触及它