Java对象的大小由三部分组成:对象头(Object Header)、实例数据(Instance Data) 和 对齐填充(Padding)。
一、对象头(Object Header)
对象头是每个Java对象都必须包含的部分,它存储了对象的元数据,主要包括以下两个部分:
1. Mark Word(标记字段)
存储对象的运行时信息,如:
哈希码(HashCode)
GC分代年龄
锁状态标志(无锁、偏向锁、轻量级锁、重量级锁)
线程持有的锁
偏向线程ID与偏向时间戳
在64位JVM中,Mark Word通常占 8字节(默认开启指针压缩时)。
2. 类型指针(Class Pointer)
指向该对象所属类的元数据(即方法区中的类信息)。
在64位JVM中,如果开启了指针压缩(默认开启-XX:+UseCompressedClassPointers),类型指针占 4字节;否则占 8字节。
⚠️ 如果对象是数组,对象头还会包含一个 数组长度字段,占4字节。
二、实例数据(Instance Data)
实例数据是对象中定义的非静态字段的实际内容,其大小取决于字段类型和数量。JVM会按照特定规则对字段进行排序以减少填充,排序规则如下:
long / double → 8字节
int / float → 4字节
short / char → 2字节
byte / boolean → 1字节(注意:每个boolean单独占1字节,不会压缩为1bit)
例如,一个类定义如下:
public class Example {
long a;
int b;
byte c;
Object d;
}
在开启指针压缩的64位JVM中,字段可能按以下顺序排列:
a (8字节)
b (4字节)
c (1字节) + 填充(3字节)
d (4字节)
因此,实例数据总大小为:8 + 4 + 1 + 3 + 4 = 20字节。
三、对齐填充(Padding)
为了提高内存访问效率,JVM要求对象的总大小必须是 8字节的整数倍。如果对象的实际大小不是8的倍数,则会通过填充字节来补齐。
例如,若对象头为16字节,实例数据为20字节,则总大小为36字节。由于36不是8的倍数,需向上对齐到40字节(5×8),因此需要填充4字节。
总结
Java对象的大小 = 对象头大小 + 实例数据大小 + 对齐填充大小
在默认情况下(64位JVM + 开启指针压缩):
对象头大小:16字节
实例数据大小:根据字段类型和数量计算
对齐填充:确保总大小为8的倍数

954

被折叠的 条评论
为什么被折叠?



