java对象创建本质是jvm协同堆、栈、方法区严格按序执行的原子过程:先类加载检查(含双亲委派),再堆内存分配(指针碰撞/空闲列表+tlab保障线程安全),接着内存初始化与对象头填充,然后执行方法赋予业务语义,最后在栈中建立引用完成可见性闭环。

Java 中对象的创建过程本质是 JVM 在内存中协同堆、栈、方法区完成的一系列原子操作,不是简单“分配一块内存”就完事。整个过程严格按序执行,每一步都影响后续行为,尤其涉及线程安全与内存布局细节。
类加载检查:先确认“模板”是否就位
执行 new Person() 时,JVM 首先查常量池里有没有 Person 的符号引用;再确认该类是否已完成加载、验证、准备、解析和初始化。没加载就触发双亲委派机制去加载 Person.class 文件——这步不走完,后面所有内存动作都不会发生。
堆内存分配:按需划出空间,兼顾并发安全
类结构确定后,对象大小即固定。JVM 在 Java 堆中划分内存,方式取决于垃圾收集器:
- 使用 Serial、ParNew 等带压缩能力的 GC 时,堆内存规整 → 采用指针碰撞:移动一个分界指针即可,极快
- 使用 CMS 或 ZGC(非压缩阶段)时,堆内存碎片化 → 采用空闲列表:查表找合适空闲块,再更新记录
- 多线程下避免竞争:默认启用TLAB(本地线程分配缓冲),每个线程在堆中预占一小块私有区域,分配无需同步
内存初始化与对象头设置:让对象“可识别、可使用”
刚分配的内存立即被置为零值(不包括对象头),所以 int 字段默认为 0、boolean 为 false、引用类型为 null——这是 Java 允许字段不显式初始化就能读取的底层保障。
紧接着填充对象头,包含:
- 运行时类型信息(指向方法区中的 Class 对象)
- 哈希码(未重写 hashCode 时惰性生成)
- GC 分代年龄、锁状态标志(偏向锁/轻量级锁标记位)
执行 方法:真正赋予对象业务语义
以上步骤完成后,对象在 JVM 层已“存在”,但字段仍是默认值,逻辑未初始化。此时才调用编译生成的
- 成员变量显式赋值(如 String name = "Alice";)
- 实例初始化块({ ... })
- 构造方法体代码
这个阶段若抛异常,对象创建失败,已分配内存后续由 GC 回收。
栈中建立引用:完成“可见性”闭环
最后,JVM 将堆中对象的首地址(或句柄池地址,取决于虚拟机配置)写入当前线程栈帧的局部变量表,比如赋给变量 Person p。从此,代码可通过该引用访问堆中对象——访问方式分两种:
- 直接指针:栈中 reference 直接存对象地址,速度快,HotSpot 默认采用
- 句柄访问:reference 存句柄地址,句柄中再存对象实例数据和类型数据地址,利于 GC 移动对象时只改句柄不改引用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











