Java对象内存布局严格分为对象头、实例数据和对齐填充三部分:对象头含Mark Word和类型指针,实例数据按字段宽度重排序以减少填充,对齐填充确保总大小为8字节倍数,从而提升CPU缓存访问效率并缓解伪共享。

Java 对象在内存中的对齐不是靠“计算公式”硬套,而是由 JVM 按固定规则逐步安排出来的。核心就三点:字段重排、字段对齐、整体补齐。下面分步讲清楚怎么一步步得出最终占用大小。
字段按类型大小重排序
JVM 不按你代码里声明的顺序放字段,而是把宽的字段优先往前排,常见排序是: - long / double(8 字节) - int / float(4 字节) - short / char(2 字节) - byte / boolean(1 字节) - 引用类型(4 字节或 8 字节,取决于是否开启压缩指针)比如这个类:
class A {
byte b;
int i;
long l;
}实际布局顺序会变成 l → i → b,而不是 b → i → l,目的是减少中间填充。
每个字段起始位置必须对其自身宽度对齐
- byte / boolean:起始地址 % 1 == 0(天然满足) - short / char:起始地址 % 2 == 0 - int / float:起始地址 % 4 == 0 - long / double / 引用(64位未压缩):起始地址 % 8 == 0例如:byte b; int i; 中,b 占 1 字节,偏移为 0;i 要从 4 开始(因需 % 4 == 0),中间自动补 3 字节填充。
立即学习“Java免费学习笔记(深入)”;
整个对象大小必须是 8 字节倍数
这是硬性要求,不管内容多少,最后都要补齐到 8 的整数倍。补齐部分叫“对齐填充”,纯占位,无数据含义。 计算方式: 总大小 = 对象头 + 实例数据区域长度 + 填充字节 其中: - 64 位 JVM + 开启压缩指针:普通对象头 = 12 字节(Mark Word 8B + Klass Pointer 4B) - 数组对象头 = 16 字节(+ length 4B) - 实例数据区域长度 = 所有字段按重排后+填充后的累计偏移 - 填充字节 = (8 − (对象头 + 实例数据) % 8) % 8举个例子:new Object()
- 对象头 = 12B
- 实例数据 = 0B
- 12 % 8 = 4 → 需补 4B → 总大小 = 16B
再如:class X { byte a; long b; }
- 重排后:
b(8B, 偏移 0) →a(1B, 偏移 8) - 实例数据区域长度 = 8 + 1 = 9
- 对象头 12B + 实例数据 9B = 21B → 21 % 8 = 5 → 补 3B → 总大小 = 24B


















