Java对象内存大小由对象头、实例数据、对齐填充三部分组成:对象头在64位+压缩指针下为16字节(Mark Word 8字节+Class Pointer 4字节,按8字节对齐补齐),实例数据按字段重排序后累加,最后整体向上对齐至8字节倍数。

Java对象占用的内存大小不是简单把字段加起来,而是受JVM实现、平台架构(32/64位)、是否开启指针压缩(-XX:+UseCompressedOops)等影响。估算时需分三块:对象头、实例数据、对齐填充。
对象头(Header)占多少?
对象头包含Mark Word和Class Pointer(类型指针),可能还有数组长度(仅数组对象)。常见情况如下:
- 64位JVM + 关闭指针压缩:Mark Word(8字节) + Class Pointer(8字节) = 16字节
- 64位JVM + 开启指针压缩(默认开启):Mark Word(8字节) + Class Pointer(4字节) = 12字节 → 实际按8字节对齐,补齐为16字节
- 32位JVM:Mark Word(4字节) + Class Pointer(4字节) = 8字节
注意:Mark Word在锁膨胀、GC标记等状态下会复用结构,但估算常规对象时按固定大小算即可。
实例数据(Instance Data)怎么加?
就是所有非静态、非瞬态(non-static, non-transient)字段的大小,按JVM字段重排序后的布局算(不一定按代码顺序)。JVM会把相同宽度的字段归堆,从宽到窄排列,以减少填充。
立即学习“Java免费学习笔记(深入)”;
- long / double → 8字节
- int / float → 4字节
- short / char → 2字节
- byte / boolean → 1字节(注意:不会被压缩成1 bit;每个boolean单独占1字节,不共享)
- 引用类型(如String、Object)→ 在64位+压缩指针下占4字节;否则占8字节
例如:class A { long a; int b; byte c; Object d; } 开启压缩指针时,重排后可能是:a(8) + b(4) + c(1) + padding(3) + d(4) → 实例数据共20字节
对齐填充(Padding)为什么必须有?
JVM要求对象总大小是8字节的整数倍(即按8字节对齐)。这是为了CPU访问效率,尤其在多核缓存行(Cache Line)对齐时更关键。
- 对象头16字节 + 实例数据20字节 = 36字节 → 向上对齐到40字节(5×8)
- 如果头16 + 数据8 = 24 → 已对齐,无需填充
- 如果头16 + 数据1 = 17 → 填充至24字节
快速估算口诀(64位 + 压缩指针,默认场景)
记住这个常用组合(也是HotSpot Server VM默认):
- 对象头:16字节(固定)
- 每个引用字段:4字节
- long/double:8字节
- int/float:4字节
- short/char:2字节
- byte/boolean:1字节(别信“boolean只占1 bit”)
- 最后结果向上对齐到8的倍数
比如空对象 new Object():头16字节 → 对齐后仍是16字节; new Integer(1):头16 + value(int,4) = 20 → 对齐为24字节。
基本上就这些。实际生产中可用JOL(Java Object Layout)工具验证,它能精确打印字段偏移、大小和对齐细节,比手算靠谱得多。










