java对象在堆中内存占用=对象头12b+实例字段实际占用+对齐填充(补至8b倍数);对象头含mark word 8b与klass pointer 4b;引用类型字段按4b计,不包含所指对象内存。

Java对象在堆中的内存占用不是简单加总字段大小,而是受JVM对象布局规则严格约束。要精细化计算,必须分三步:算清对象头、累加字段实际占用、补齐对齐填充。
对象头固定开销(12字节)
在64位JVM开启指针压缩(默认启用)时,对象头包含:
- Mark Word:8字节(存储哈希码、锁状态、GC分代年龄等)
- Klass Pointer:4字节(指向类元数据的指针)
合计12字节。注意:空对象(new Object())就占这12字节,不是8字节——网上说“Object占8字节”是忽略了Klass Pointer。
字段内存按声明顺序紧凑排列,但需考虑对齐
JVM按字段声明顺序分配内存,并优先将占用大的字段往前排(HotSpot会自动重排序以减少padding,但计算时仍建议按实际布局逻辑理解)。基本类型字段大小固定:
-
long/double:8字节 -
int/float:4字节 -
char/short:2字节 -
byte/boolean:1字节(实际存储通常用1字节,不打包成bit)
⚠️ 关键细节:多个1字节字段(如byte a; boolean b; byte c;)会被合并存放在同一字节对齐单元内,但若中间插入4字节字段,就会强制断开并可能引入填充。
最后必须向上对齐到8字节倍数
对象总大小 = 对象头(12) + 所有字段实际占用 + padding(0~7字节)
结果必须是8的整数倍。例如:
- 字段为
byte a; int b;→ 头12 + a1 + b4 = 17 → 补7 → 总24字节 - 字段为
long a; byte b;→ 头12 + a8 + b1 = 21 → 补3 → 总24字节 - 字段为
byte a; long b; byte c;→ JVM重排为long b; byte a; byte c;→ 12+8+1+1=22 → 补6 → 总28字节
引用类型字段统一按4字节计算(指针压缩下)
无论引用的是String、Integer还是自定义对象,字段本身只存一个地址,占4字节。它不等于被引用对象的大小——那是“深内存”,需单独递归计算。
例如:class A { int x; String s; } 中,s字段贡献4字节,而s指向的String对象另占至少16字节(String对象头12 + char[]引用4 → 至少16),再加char[]自身开销。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











