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中非常频繁,因此这类开销积少成多也是一项极为可观的执行成本。
本文来自博客园,作者:cxbks,转载请注明原文链接:https://www.cnblogs.com/cxbks-write-down/articles/15551818.html