java对象创建共五步:类加载检查→内存分配→初始化零值→设置对象头→执行方法;其中内存分配依堆规整性采用指针碰撞或空闲列表,多线程下通过cas或tlab保障安全。

Java 中对象的创建不是简单的一行 new 就完事,而是 JVM 在堆内存中严格按步骤完成的一整套流程。整个过程共五个核心环节,环环相扣,缺一不可。
类加载检查是前提
执行 new 指令时,JVM 第一时间不会分配内存,而是先查常量池里有没有该类的符号引用;再确认这个类是否已完成加载、验证、准备、解析和初始化。如果没加载,就触发双亲委派机制去加载——没类,就根本谈不上创建对象。
内存分配看堆是否规整
类加载完成后,对象大小已知,JVM 从堆中划出对应空间。具体怎么划,取决于当前使用的垃圾收集器:
- 指针碰撞(Bump the Pointer):适用于 Serial、Parallel 等带压缩能力的 GC。堆内存被整理成“已用区”和“空闲区”两块,中间一个指针作分界。分配时只需把指针向空闲方向挪动对象所需字节数,极快且无碎片。
- 空闲列表(Free List):适用于 CMS、G1 等不压缩或部分压缩的 GC。堆内存交错混杂,JVM 维护一张记录可用内存块的表,每次分配需遍历查找足够大的空闲块,速度慢、易受碎片影响。
并发分配靠 CAS 或 TLAB
多线程同时 new 对象,可能抢同一块内存。JVM 用两种方式规避冲突:
- CAS + 重试:对指针移动操作加原子性校验,失败就重试,确保不覆盖。
-
TLAB(线程本地分配缓冲):默认开启(
-XX:+UseTLAB)。每个线程在 Eden 区预分配一小块私有内存,对象优先在 TLAB 中分配,避免锁竞争。只有 TLAB 不足时才同步申请主堆空间。
后续三步是对象成型的关键
内存分配完后,JVM 还要继续走完剩下几步:
-
初始化零值:把分配到的内存所有字节设为 0(不包括对象头),让
int变成 0、boolean变成false、引用类型变成null,保障字段可安全读取。 - 设置对象头:填入哈希码、GC 分代年龄、锁状态标志、指向类元数据的类型指针等关键信息。64 位系统下,Mark Word 占 8 字节,类型指针占 4 字节(开启压缩)或 8 字节(未压缩)。
-
执行
<init></init>方法:调用构造函数,按程序员逻辑给字段赋值、执行初始化代码块——这才是你写的构造逻辑真正起效的地方。
对象最终落在堆里,按 8 字节对齐
对象在堆中的实际内存布局由三部分组成:对象头、实例数据、对齐填充。其中对齐填充不是可有可无——JVM 要求对象起始地址必须是 8 字节的整数倍,不足就补空白字节。所以哪怕一个只有 1 字节字段的类,对象大小也至少是 16 字节(含对象头 12 字节 + 对齐填充)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











