Java中new Object()创建的空对象在64位HotSpot JVM(默认开启指针压缩)下占16字节:对象头12字节(Mark Word 8字节 + 压缩Klass Pointer 4字节),实例数据0字节,再经8字节对齐填充4字节。

在 Java 中,new Object() 创建的实例不是“零开销”的空壳,它有确定且可验证的内存占用。主流 HotSpot JVM(64 位、JDK 8 及以后)默认开启指针压缩,此时一个空对象实际占 16 字节 —— 这个数字由对象头结构和内存对齐规则共同决定,不是随意估算的结果。
对象内存布局的三个固定组成部分
每个 Java 对象在堆中都按顺序划分为三块:
- 对象头(Header):包含 Mark Word(8 字节,存哈希码、锁状态、GC 分代年龄等)和 Klass Pointer(类元数据指针);
-
实例数据(Instance Data):字段内容区域,
Object类无任何字段,因此为 0 字节; - 对齐填充(Padding):JVM 要求对象总大小必须是 8 字节的整数倍,不足则补零。
为什么是 16 字节,而不是 8 或 12?
关键在于指针压缩与对齐的组合效应:
- 默认开启
-XX:+UseCompressedOops(JDK 8–15+ 小堆仍默认启用),Klass Pointer 压缩为 4 字节; - 对象头 = 8(Mark Word) + 4(Klass Pointer) = 12 字节;
- 实例数据 = 0 字节 → 当前累计 12 字节;
- 12 不是 8 的倍数,需向上补齐到最接近的 8 的倍数,即 16 字节,补 4 字节填充。
不同配置下的实际大小对比
同一行代码,在不同 JVM 参数下结果不同,但都遵循相同逻辑:
-
关闭指针压缩(
-XX:-UseCompressedOops):Klass Pointer 回到 8 字节 → 对象头 16 字节 → 总大小仍是 16 字节(无需填充); - 32 位 JVM:Mark Word 和 Klass Pointer 各 4 字节 → 对象头 8 字节 → 总大小 8 字节(已满足对齐);
- JDK 15+ 大堆或显式禁用压缩:行为同关闭压缩,对象头 16 字节,总大小 16 字节(无填充)或 24 字节(若后续加字段触发新对齐)。
验证方式必须可靠,不能靠猜测
不要用 Runtime.totalMemory() 差值法,误差极大。推荐两种实测方法:
- 使用 JOL(Java Object Layout):引入
org.openjdk.jol:jol-core,调用ClassLayout.parseInstance(new Object()).toPrintable(),输出明确标注size: 16; - 使用
Instrumentation.getObjectSize()(需通过 agent 方式加载,生产环境慎用); - 注意:
Object o = new Object()中的变量o是栈上引用(4 或 8 字节),它不计入对象自身大小——JOL 测的是堆中那个实例的 shallow size。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











