回答
Java 中类的生命周期主要包括加载、链接、初始化、使用和卸载五个阶段,其中连接又分为验证、准备和解析三个步骤。
- 加载:加载是将类的字节码文件(.class 文件)加载到 JVM 中的过程。
- 链接:链接分为验证、准备、解析三个步骤:
- 验证:主要是验证加载字节码是否合法,不会破坏 JVM 的安全性。这个过程包括检查类文件的结构、数据类型的准确性等。
- 准备:在这个步骤,JVM 会为类的静态变量分配内存空间并初始化为默认值。对于非静态变量,JVM 是在对象实例化时才分配内存空间。
- 解析:这个步骤主要就是把 Class 文件中、常量池中的符号引用转换为直接引用。主要解析的是类或接口、字段、类方法、接口方法、方法类型、方法句柄等符号引用。
- 初始化:在这个阶段,类的静态初始化块和静态变量会被执行和初始化。
- 使用:一旦类被初始化,就可以被实例化或调用。
- 卸载:当没有任何实例引用一个类,并且这个类在内存中不再被使用时,JVM的垃圾回收机制会将其从内存中卸载。
详解
加载阶段
加载阶段负责将类的字节码加载到 JVM 中。这个阶段主要就是做三件事:
- 通过一个类的全限定名来获取定义此类的二进制字节流。
- 将读取的二进制字节流存储在 JVM 的方法区中。
- 在内存(堆区)中生成一个代表这个类的
java.lang.Class
对象,Class 对象封装了类在方法区内的数据结构,并提供了访问方法区内的数据结构的接口。
类加载的过程由类加载器负责,更多关于类加载器的知识请阅读面试题:JVM 中有哪些类加载器?
链接阶段
链接阶段分为三个步骤:验证、准备和解析。
验证阶段
验证阶段的主要目的是确保类的字节码符合JVM的规范,在这个阶段,JVM 会做如下几个验证:
- 文件格式验证:检查
.class
文件的基本格式,包括魔数、版本号、常量池等。 - 数据类型验证:确保字节码中的数据类型符合Java的类型系统。
- 访问权限检查:确保类和成员的访问修饰符符合 Java 语言的规则。例如,私有成员是否只能在该类中访问。
- 父类验证:检查类的父类是否存在,并且父类的结构是否有效。这可以防止不合法的类继承。
- 符号引用验证:验证符号引用的直接引用是否存在。
当然,实际的验证阶段比上面会更加复杂,验证的项目也会多很多,但大体上都是在这几个方向:格式、语义、字节码、符号引用。