深入理解Java虚拟机之对象的内存布局、访问定位

内存布局

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

对象头

对象头分为两个部分,第一部分存储自身的 运行时数据 ,如对象的哈希码、GC分代年龄、标志位等。这部分数据的长度在32位和64位的虚拟机中分别为32bit和64bit,官方称它为“Mark World”,Mark Word被设计为一个非固定的数据结构,以便在极小的内存空间内存储尽量多的信息,它会根据对象的状态复用自己的存储空间。32位HotSpot虚拟机对象头Mark Word存储内容如下:

深入理解Java虚拟机之对象的内存布局、访问定位

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

如果对象是一个Java数组,对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但从数组的元数据却无法确定数组的大小。

实例数据

实例数据部分是对象真正存储的有效信息,也是程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录下来。这部分的存储顺序会受到虚拟机分配策略参数(FieldsAllocationStyle)和Java字段在Java源码中定义的顺序的影响。HotSpot虚拟机默认的分配策略为longs/doubles、ints、shorts/chars、bytes/boolean、oops(ordinary object pointers),相同宽度的字段总是被分配到一起。

对齐填充

对齐填充并不是必然存在的,仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象的起始地址必须是8字节的整倍数,而对象头刚好是8字节的整倍数,所以当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

访问定位

建立对象是为了使用对象,我们的Java程序需要通过栈上的reference数据来操作堆上的具体对象。

访问方式

  • 句柄访问 :在堆中划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据与类型数据各自的地址信息。

    深入理解Java虚拟机之对象的内存布局、访问定位

  • 直接指针访问 :reference中存储内容为对象地址。

    深入理解Java虚拟机之对象的内存布局、访问定位

两种访问方式优势对比

句柄访问最大的好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据的指针,而无需修改reference本身。

直接指针访问的最大好处是速冻更快,节省了一次指针定位的时间开销。

原文 

https://juejin.im/post/5bacd861f265da0ac55e5931

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 深入理解Java虚拟机之对象的内存布局、访问定位

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址