创建对象的步骤
以下是创建对象的具体步骤及详细说明,结合关键流程与原理分析:
1.判断对象是否加载、链接阶段、初始化阶段
类加载检查是对象创建的第一步。当遇到new
指令时,虚拟机会检查该指令的参数是否能在常量池中定位到类的符号引用,并检查该类是否已被加载、解析和初始化。若未加载,需先执行类加载过程。
链接分为三个子步骤:
- 验证:确保类信息符合虚拟机规范,避免安全问题。
- 准备:为类的静态变量分配内存并设置默认初始值(如
int
为0)。 - 解析:将符号引用转换为直接引用(如方法、字段的实际内存地址)。
执行类构造器<clinit>
方法,完成静态变量的显式初始化(如static int a = 1;
)和静态代码块的合并操作。该阶段仅执行一次。
2.分配对象内存
虚拟机为新生对象分配堆内存,分配方式取决于堆内存是否规整:
- 指针碰撞(Bump the Pointer):适用于内存规整的情况,通过移动指针划分内存。
- 空闲列表(Free List):适用于内存不规整,虚拟机维护可用内存块列表。
并发处理:
在多线程环境下,可能通过**CAS(Compare-And-Swap)或TLAB(Thread Local Allocation Buffer)**避免分配冲突。TLAB为每个线程预先分配一小块内存,对象优先在TLAB中分配。
3.初始化内存空间
将分配的内存空间(不包括对象头)初始化为零值。所有实例变量的默认值被设置(如int
为0,boolean
为false
),确保对象字段无需额外初始化即可使用。
4.设置对象头
对象头包含两类信息:
- Mark Word:存储哈希码、GC分代年龄、锁状态标志等。
- 类型指针:指向类元数据的指针,用于确定对象属于哪个类。
若启用压缩指针(64位JVM),对象头可能包含压缩后的类型指针。
5.执行<init>
方法
调用对象的构造方法(即<init>
),按程序员定义的代码初始化实例字段和执行构造函数逻辑。此时对象才完全完成创建。