对象的内存是如何布局的?
在虚拟机(jvm)中对象的内存布局被分为:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
对象头(Header)
包含两类信息:自身运行时数据(Mark Word)与类型指针(Class Pointer)。
自身运行时数据包含:哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32个比特和64个比特,官方称它为“Mark Word”。
注:64位虚拟机上面有一个压缩指针选项-XX:+UseCompressedOops,默认是开启的Pointer部分就会压缩为4字节,此时对象头大小就会缩小到12字节。
类型指针:虚拟机通过这个指针来查找对象是哪个类的实例。
实例数据(Instance Data)
实例数据部分是对象真正存储的有效信息,即程序代码中所定义的各种类型的字段内容,包含子父类所有字段信息。受到虚拟机分配策略参数(-XX:FieldsAllocationStyle参数)和字段在Java源码中定义顺序的影响。分配顺序为longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers,OOPs)
对齐填充(Padding)
对齐填充非必须存在,也没有特别的含义,只起到占位符的作用。
注意:任何对象的大小都必须是8字节的整数倍
对象的访问定位
java程序通过栈上的reference数据来操作堆上的具体对象。
reference又是什么?
对象的句柄地址。
访问方式有哪些?
句柄:java堆会划分出一块内存来作为句柄池,reference中存储对象的句柄地址,而句柄中又包含了实例数据与类型数据各自的具体地址信息。
优式:稳定
直接指针:java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址。
优式:速度更快。
注意:HotSpot用的是直接指针访问方式。
最后
本文对对象内存如何布局中的Mark Word仅作了简要介绍,因为该参里面还涉及后续的锁在32位和64位存储结构,说真的那块已经非常深入了,特别Mark Word里面存放锁的信息,非常值得单独来研究深入,当然篇幅有限由后续单独文章再详细深入。
参考文章:
https://blog.csdn.net/qq_36434742/article/details/106854061
https://my.oschina.net/u/3847203/blog/3014994