Java中new创建对象包含五个严格步骤:1.类加载检查;2.内存分配;3.初始化零值;4.设置对象头;5.执行构造方法。JVM保障全过程原子性,防止半初始化对象被访问。

Java中使用new关键字创建对象时,并不是简单地“分配内存”就完事了,而是一系列严格、有序的内部步骤。理解这些步骤,有助于掌握对象生命周期、类加载机制和初始化逻辑。
1. 类加载检查(Class Loading Check)
虚拟机首先检查该类是否已被加载、解析和初始化。若尚未加载,会触发类加载过程:加载 → 验证 → 准备 → 解析 → 初始化。只有完成初始化后,才能继续后续操作。
2. 内存分配(Memory Allocation)
在堆内存中为新对象划分空间。分配方式取决于垃圾收集器策略:
- 指针碰撞(Bump the Pointer):适用于内存规整(如Serial、ParNew),移动空闲指针即可;
- 空闲列表(Free List):适用于内存不规整(如CMS),需从记录空闲块的列表中查找合适大小;
- 如果启用了TLAB(Thread Local Allocation Buffer),优先在本地线程缓冲区中分配,提升并发性能。
3. 初始化零值(Zero Initialization)
分配完成后,虚拟机会将对象内存中所有字段初始化为零值(如int→0、long→0L、reference→null、boolean→false)。这一步保证了即使未显式赋值,字段也能安全访问,不出现随机值。
立即学习“Java免费学习笔记(深入)”;
4. 设置对象头(Object Header Setup)
在对象内存起始处写入对象头信息,包括:
- 哈希码(可能延迟计算)、GC分代年龄、锁状态标志;
- 类型指针(指向Class对象的指针),用于确定该实例属于哪个类;
- 数组长度(仅数组对象有)。
5. 执行构造方法(<init> 方法)
调用构造函数前,JVM会确保父类构造器已执行(隐式或显式super()),然后执行当前类的实例初始化方法<init>——这是编译器生成的特殊方法,包含:
- 字段显式初始化语句(如
private int x = 10;); - 实例代码块(
{ ... }); - 构造函数中的代码。
注意:new表达式的返回值,是这个已完全初始化的对象引用(而非未初始化的原始内存地址)。
整个过程由JVM严格保障原子性:即使多线程同时new同一类对象,每个对象都独立完成上述全部步骤,不会出现“半初始化对象”被其他线程看到的情况(前提是构造函数内不泄露this引用)。


















