java对象实际大小=对象头+实例数据+对齐填充,必须为8字节整数倍;对象头默认12字节(64位+压缩指针),字段按宽度降序排列,填充不可消除但可最小化,jol工具可精确测量。

Java 中计算一个对象在 JVM 中实际占用的字节数,不能直接用 sizeof(Java 没有该操作符),需要结合 JVM 内存布局规则、对齐机制和工具辅助来估算或测量。核心思路是:对象大小 = 对象头 + 实例字段(含继承)+ 对齐填充,且受 JVM 参数(如是否开启压缩指针)影响。
理解 JVM 对象内存布局
JVM 中普通对象(非数组)内存结构通常包括三部分:
- 对象头(Header):包含 Mark Word(锁状态、GC 分代年龄、哈希码等,一般 8 或 12 字节)和 Class Pointer(指向类元数据,开启压缩指针时为 4 字节,否则 8 字节);
- 实例数据(Instance Data):按字段宽度从大到小排列(JVM 优化策略),包括父类字段;
- 对齐填充(Padding):保证对象总大小是 8 字节的整数倍(主流 HotSpot 默认对齐单位)。
手动估算对象大小(以 64 位 JVM 为例)
假设使用默认参数(-XX:+UseCompressedOops 开启,即压缩指针),以如下类为例:
class Person {
int id; // 4 字节
String name; // 4 字节(引用,压缩指针)
boolean flag; // 1 字节
}
估算步骤:
- 对象头:Mark Word(8 字节) + 压缩 Class Pointer(4 字节) = 12 字节;
- 字段:id(4)+ name(4)+ flag(1)= 9 字节;但 JVM 会重排序为
name(4)、id(4)、flag(1)→ 当前累计 9 字节; - 字段后需对齐到 8 字节边界:12(头) + 9(字段) = 21 → 向上对齐到 24;
- 最终大小 = 24 字节(不含数组元素,String 对象本身另算)。
注意:关闭压缩指针(-XX:-UseCompressedOops)会使引用变为 8 字节,对象头变成 16 字节,结果不同。
用 JOL(Java Object Layout)精确测量
最推荐方式:使用 JOL 工具,它通过 Unsafe 和 JVM 内部 API 获取真实布局。
- Maven 引入:
<dependency><groupid>org.openjdk.jol</groupid><artifactid>jol-core</artifactid><version>0.17</version></dependency> - 代码示例:
import org.openjdk.jol.info.ClassLayout;
public class Main {
public static void main(String[] args) {
System.out.println(ClassLayout.parseInstance(new Person()).toPrintable());
}
}
输出会清晰显示:对象头各字段偏移、字段位置、padding 区域、总大小(如 "INSTANCE SIZE: 24 bytes")。
注意易忽略的关键点
- 数组对象额外开销:数组有 4 字节长度字段,对象头也略不同(如多 4 字节 length);
- String 等内置类要分层看:new String("abc") 占用不止 24 字节——它内部 char[] 又是一个独立对象,需叠加计算;
- Shallow Size vs Retained Size:JOL 给的是 shallow size(自身占用),retained size(包括独占引用的对象)需用 MAT 或 VisualVM;
- 不同 JVM 版本/厂商可能有差异:OpenJDK、Zing、GraalVM 的对象布局策略不完全一致。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











