Java对象内存布局

在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充。

另外,Java中对象的内存布局分为两种情况,非数组对象和数组对象,区别是数组对象头中需要额外的空间存储数组的长度length。

 

对象头(Object Header)

   对象头又分为MarkWord和Class Pointer。

  • MarkWord:标记存储对象本身运行时的数据,包含哈希值(指向对象在堆中的首地址值)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。在32位系统占4字节,在64位系统中占8字节

  • ClassPointer:类型指针,存储的是对象指向它的Class对象(其对应的类元数据对象)的首地址。在32位系统占4字节,在64位系统中占8字节

  • Length:只在数组对象中存在,用来记录数组的长度,占用4字节

  对象头中Mark Word 在不同状态下的存储内容如下:

锁状态 存储内容(剩余bit) 是否为偏向锁(1bit) 锁标志位(2bit)
无锁 对象哈希码、分代年龄 0 01
偏向锁 偏向线程ID、偏向时间戳、对象分代年龄 1 01
轻量级锁 指定锁记录的指针 无此bit 00
重量级锁 指向重量级锁的指针 无此bit 10
GC标记 空,不需要记录记录信息 无此bit 11

  

实例数据(Instance data)

  • Instance data:对象实例数据,存储本类对象的成员变量和所有可见的父类成员变量。(这里不包括静态成员变量,因为其是在方法区维护的)

 

对齐填充(Padding)

  • Padding:Java对象的存储空间分配单位是8个字节,不足8字节,也会分配8字节进行填充。即所有Java对象占用bytes数必须是8的倍数,padding的作用就是补充字节,保证对象是8字节的整数倍。64位计算机上Java对象头的大小刚好是8的2倍,因此当实例数据部分没有对齐时,就需要通过对齐填充来补全。

指针压缩

   -XX:+UseCompressedOops 可以压缩指针,将占用的空间压缩为原来的一半(4字节),起到节约空间的作用,classpointer参数大小就受到其影响。

 

Object o = new Object()到底占用多少个字节?

  • 在开启指针压缩的情况下,markword占用8字节,classpoint占用4字节,Instance data无数据,总共是12字节,由于对象需要为8的整数倍,Padding会补充4个字节,总共占用16字节的存储空间。

  • 在没有指针的情况下,markword占用8字节,classpoint占用8字节,Instance data无数据,总共是16字节。

END.

原文地址:https://www.cnblogs.com/yangyongjie/p/14571672.html