java对象在堆内存中由对象头(含mark word和class pointer)、实例数据(按字段宽度降序排列)和对齐填充(padding)三部分组成。
Java对象在堆内存中由哪几部分组成
Java对象在堆内存中不是一块连续的“裸数据”,而是有固定结构的布局,主要包括三块:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。这个结构由JVM规范约定,但具体实现(如HotSpot)有细节差异。
对象头又分为两部分:Mark Word(存储哈希码、GC分代年龄、锁状态等)和Class Pointer(指向该对象所属Class元数据的指针)。32位JVM下对象头通常8字节,64位默认12字节(开启指针压缩后也是12字节)。
- 开启指针压缩(
-XX:+UseCompressedOops,默认开启)时,Class Pointer占4字节;否则占8字节 -
Mark Word在无锁状态下存哈希码(若未调用hashCode()则为0)、分代年龄(4位)、偏向锁标记等,共8字节(64位平台) - 实例数据按字段宽度从大到小排列(
long/double→int/float→char/short→byte/boolean),以提升内存访问效率
为什么new出来的对象大小不等于字段大小之和
因为JVM要求对象起始地址必须是8字节的整数倍(即对象总大小需对齐到8字节边界),所以会在实例数据末尾补上若干字节的Padding。这是唯一原因——不是为了缓存行对齐,也不是为了GC效率,纯粹是HotSpot的内存分配策略要求。
例如:class A { byte a; },字段只占1字节,但对象实际占用16字节(对象头12字节 + 实例数据1字节 + 填充3字节 = 16字节)。
立即学习“Java免费学习笔记(深入)”;