HotSpot中对象的内存布局

文章参考《深入理解Java虚拟机》第3版

HostSpot中对象:Header:对象头[Mark Word-8个字节:关于锁的信息记录在这里+class pointer-4个字节:类型指针]+Instance Data(实例数据)+Padding(对齐填充)

1、对象头(Header)

对象头包含存储对象自身运行时的数据(Mark Word)和类型指针(Class Pointer)

1.1、HotSpot虚拟机对象头Mark Word

锁状态 25位 31位 1位 4bit 1bit 2bit
锁标志位
无锁态 unused hashcode unused 分代年龄 0 01
锁状态 54位 2位 1位 4bit 1bit 2bit
锁标志位
偏向锁 当前线程指针JavaThread+ Epoch unused 分代年龄 1 01
锁状态 62位 2bit
锁标志位
轻量级锁 指向线程栈中Lock Record的指针 00
重量级锁 指向重量级锁的指针 10
GC标记 CMS过程用到的标记信息 11

1.2、类型指针

类型指针即对象指向它的类型元数据的指针,Java虚拟机通过这个指针来确定该对象是哪个类型的实例。

2、实例数据(Instance Data)

对象真正存储的有效信息

#2.1、-XX:FieldsAllocationStyle 参数
# 相同宽度的字段总是被分配到一起存放,在父类中定义的变量会出现在子类之前
#2.2、+XX:CompactFields 参数为true(默认为true)
# 子类中较窄的变量也允许插入父类变量的空隙之中

3、对齐填充(Padding)

  • HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,也就是任何对象的大小都必须是8字节的整数倍。
  • 对象头部分已经被设计成正好是8字节的倍数(1倍或者2倍),因此,如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。

4、对象的访问定位

虚拟机HotSpot一般使用直接指针方式进行对象访问

4.1、使用句柄访问

Java堆中将可能会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自具体的地址信息;使用句柄来访问的最大好处就是reference中存储的是稳定句柄地址,在对象呗移动时只会改变句柄的实例数据指针,而reference本身不需要被修改。

4.2、使用直接指针访问

Java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息,reference中存储的直接就是对象地址,如果只是访问对象本身的话,就不需要多一次间接访问的开销;使用直接指针来访问最大的好处就是速度更快,它节省了一次指针定位的时间开销,由于对象访问在Java中非常频繁,因此这类开销积少成多也是一项极为可观的执行成本。

虚拟机对象访问.jpeg

posted on 2021-11-14 14:46  cxbks  阅读(62)  评论(0)    收藏  举报