jvm对象创建严格遵循六步流程:类加载检查→分配内存→初始化零值→设置对象头→执行构造方法→指针压缩优化;类加载检查是前提,需确认类已加载、验证、准备、解析、初始化,否则触发双亲委派加载,失败则抛异常。

Java 中对象创建不是简单的一行 new 就完事,而是 JVM 严格按顺序执行的多步过程,涉及类加载、内存划分、线程安全和对象结构初始化。整个流程环环相扣,每一步都影响性能与稳定性。
类加载检查是对象创建的前提
JVM 遇到 new 指令时,第一件事不是分配内存,而是查常量池里有没有该类的符号引用,并确认这个类是否已完成加载、验证、准备、解析和初始化。如果没加载,就触发双亲委派机制去加载;加载失败直接抛异常。静态代码块和静态变量赋值就发生在这个阶段,且 JVM 保证只执行一次、线程安全。首次 new 某个类慢,往往卡在这里。
内存分配取决于堆是否规整
类加载完成后,JVM 才知道对象占多大空间,接着从堆中划出对应大小的内存。具体怎么划,看垃圾收集器:
- 用 Serial 或 Parallel 收集器时,堆内存被整理得规整,采用指针碰撞法:空闲内存和已用内存各占一边,分配时只需把分界指针挪动一段距离,速度快、无碎片。
- 用 CMS 或 G1(未开启压缩)时,堆内存不规整、有碎片,改用空闲列表法:JVM 维护一张可用内存块列表,每次分配都要遍历找足够大的空闲块,速度较慢。
多线程下内存分配如何不冲突
高并发场景中,多个线程同时 new 对象,可能争抢同一块内存地址。JVM 用两种方式规避:
- CAS + 失败重试:对指针更新操作加乐观锁,失败就重试,直到成功。
-
TLAB(线程本地分配缓冲):默认开启(
-XX:+UseTLAB),每个线程在 Eden 区预分配一小块私有内存。对象优先在 TLAB 分配,避免竞争;只有对象太大或 TLAB 不足时,才回到共享堆用 CAS 分配。
对象初始化与头信息设置同步完成
内存分配后,JVM 立即把这块空间所有字节设为零(不包括对象头),确保 int 默认为 0、boolean 为 false、引用类型为 null。紧接着填充对象头,存入:
- 哈希码、GC 年龄、锁状态标志(如偏向锁、轻量级锁等)
- 类型指针(指向方法区/元空间中的类元数据)
- 数组长度(仅数组对象有)
最后才调用你写的构造方法(<init></init>),执行字段赋值和实例代码块——这才是程序员控制的初始化逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











