在 Java 中,类加载是一个重要的过程,涉及到如何将类的字节码文件加载到 JVM 中并生成对应的 Class 对象。本文将详细介绍类加载的步骤、类加载器的工作原理以及双亲委派模型。
1. 类加载的步骤
类加载过程主要分为以下几个阶段:
1.1 加载(Loading)
- 获取字节流:通过全类名获取定义该类的二进制字节流。
- 转换为运行时数据结构:将字节流转换为方法区的运行时数据结构。
- 生成 Class 对象:在内存中生成一个代表该类的 Class 对象,作为访问这些数据的入口。
1.2 连接(Linking)
连接过程又可分为三个步骤:
-
验证(Verification):
- 确保字节码文件符合 JVM 规范,不包含安全风险。
- 包括字节码验证、符号引用验证、类型检查等。
-
准备(Preparation):
- 为类的静态变量分配内存,并设置初始值(零值)。
- 注意:实例变量的分配是在对象实例化时进行的。
-
解析(Resolution):
- 将类、方法、字段等符号引用解析为直接引用,以便后续执行时快速访问。
1.3 初始化(Initialization)
- 执行静态变量的赋值和静态块的初始化。
2. Java 对象创建的过程
Java 对象的创建过程可以分为以下步骤:
2.1 类加载检查
- 当虚拟机遇到
new
指令时,首先检查常量池中是否可以定位到该类的符号引用,并检查该符号引用是否已被加载。
2.2 分配内存
- 指针碰撞:适用于内存规整,通过分界指针快速分配内存。
- 空闲列表:适用于内存不规整,维护一个可用内存块的列表。
2.3 初始化零值
- 将分配到的内存空间初始化为零值,确保实例字段可以直接使用。
2.4 init() 操作
- 调用构造方法进行对象的初始化。
3. 类加载器
类加载器负责类的加载过程,每个类都有一个引用指向加载它的 ClassLoader。数组没有 ClassLoader,由 JVM 直接生成。
3.1 双亲委派模型
-
工作原理:
- 除了顶层的启动类加载器外,其余类加载器都有自己的父类加载器。
- 在加载类时,系统首先判断当前类是否已被加载。
- 如果未加载,则将加载请求委派给父类加载器。
- 只有当父加载器无法完成加载请求时,子加载器才会尝试加载。
-
好处:
- 避免重复加载类,提高了类的安全性和稳定性。
4. 总结
Java 的类加载机制是一个复杂而又重要的过程,包括加载、连接、初始化等多个步骤。通过双亲委派模型,Java 确保了类的唯一性和安全性,使得类加载过程更加高效和可靠。理解类加载的机制,有助于开发者在编写 Java 程序时更好地管理类的生命周期和内存。