Java中空对象(如new Object())在64位HotSpot JVM开启指针压缩时占16字节:12字节对象头(8字节Mark Word+4字节Klass Pointer)+0字节实例数据+4字节对齐填充;关闭压缩或32位JVM下仍为16字节或8字节,均由对象头和8字节对齐规则决定。

Java中空对象的内存占用由对象头和对齐填充决定
Java里没有真正“空”的对象——哪怕类里一个字段都没有,new Object() 创建的实例仍会占用内存。HotSpot虚拟机下,64位JVM默认开启指针压缩(-XX:+UseCompressedOops),此时对象头占12字节:8字节Mark Word + 4字节Klass Pointer;接着是0字节实例数据;最后按8字节对齐补零,所以总大小为16字节。
- 关闭指针压缩(
-XX:-UseCompressedOops)时,Klass Pointer变为8字节,对象头变成16字节,对齐后仍为16字节(无需额外填充) - 32位JVM对象头固定为8字节(4+4),对齐后也是8字节
-
java.lang.Object子类若只含private int字段,实例数据占4字节,加上12字节对象头,需填充4字节对齐到16字节
验证空对象大小要用Unsafe或JOL,不能靠sizeof
Java没有sizeof操作符,直接用Runtime.getRuntime().totalMemory()之类估算误差极大。可靠方式只有两种:
- 用JDK自带的
jdk.internal.misc.Unsafe(需反射获取,且JDK 17+默认禁止,需加--add-opens参数)读取objectFieldOffset并计算布局 - 更推荐用OpenJDK官方工具
JOL(Java Object Layout):Maven引入org.openjdk.jol:jol-core,然后调用ClassLayout.parseInstance(new Object()).toPrintable() - 注意:JOL输出的“size”是对象总大小,“shallow size”才是当前对象自身占用(不含引用对象),二者对空对象是一致的
数组对象不算“空对象”,但长度为0的数组也占内存
new byte[0] 和 new Object[0] 都不是空对象,而是数组实例。它们有额外的4字节长度字段(32位)或8字节(64位未压缩),因此:
- 64位+压缩指针下,
new byte[0]占16字节(12字节头 + 4字节长度 + 0填充) -
new Object[0]同样16字节,但new Object[1]立刻跳到24字节(多8字节引用存储) - 不要误把
byte[0]当“零开销容器”——它仍有对象头和对齐成本
继承、字段顺序、@Contended都会影响实际大小
看似空的对象,一旦参与继承链或加了注解,大小可能突变:
立即学习“Java免费学习笔记(深入)”;
- 子类字段若类型不同(如
longvsint),JVM会重排字段以优化对齐,可能导致填充字节增加 -
@sun.misc.Contended(需-XX:+UnlockExperimentalVMOptions -XX:+RestrictContended)会给字段前后各加128字节填充,哪怕类本身只有1个int - 使用
record定义无字段类(如record Empty() {}),其底层仍是普通对象,大小与Object一致











