关闭

java虚拟机——对象的布局、访问方式

标签: jvm布局对象存储实例
171人阅读 评论(0) 收藏 举报
分类:

对象的内存布局

在上一章节中,我们讨论了对象在虚拟机中是如何创建的,那么在对象创建后,它在内存中是如何进行布局的呢?也就是说它都有哪些区域和内容呢?
对象在内存中的布局可以分为3个区域:对象头、实例数据、对齐填充(HotSpot虚拟机中是采用这种方式)。

对象头

HotSpot虚拟机中的对象的对象头分为两部分:
第一部分为:存储了对象的HashCode(哈希码)、GC分代年龄、线程持有的锁,锁状态标志等(想要了解它们其中各个具体数据结构,大家可以单独查阅,这里就不多说啦)。
第二部分为:类型指针,就是对象是属于哪个类的,对象通过这个指针来进行确定。另外,如果对象是一个数组,那么在这部分还必须有一块用来记录数组长度的数据块,因为JVM能确定普通类的实例对象的大小,但是对于数组来说,确定大小还需要知道数组的长度。

实例数据

在介绍完对象的对象头之后,接下来的区域就是实例数据了,实例数据就是对象真正存储有用数据的一部分(可以理解为咱们对象中的成员变量等 ),就是程序代码中所定义的各种类型的字段。无论是父类继承来的还是子类中新定义的,都有记录,我们可以直接在子类中使用父类的非私有成员。

对齐填充

第三个区域就是对齐填充,这部分可以并没有太大的意义,按字面的意思就是用来填充的,因为在HotSpot虚拟机中,要求对象的大小必须是8个字节的整数倍,对象中的对象头是8字节的整数倍,那么就看实例数据部分是不是8字节的整数倍。如果实例数据部分不是8字节的整数倍,那么对齐填充就发挥功能,它将会填充补全,将实例数据部分变为8字节的整数倍。

对象的访问定位

对象的访问定位是方便我们能更好的使用对象,我们在java虚拟机栈上通过reference(引用类型)来操纵对象,而reference类型只是一个指向对象的引用,但是具体的访问方式并没有定义。所以具体如何访问一个具体的对象是由不同JVM而定的。但是目前的访问方式主要有两种:句柄访问和直接指针访问。

句柄访问

使用句柄访问对象,java堆将单独划分出一块区域用来作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了指向对象实例的数据的指针和指向对象类型数据的指针。通过下面的图就可以更加形象的了解句柄是如何访问对象的。



直接指针访问

直接指针访问方式(HotSpot VM),java栈中的reference类型就会直接指向一个实例对象,对象中包括了三部分内容,哪三部分呢?就是上面说的对象的内存布局中的三个区域:对象头、实例数据、对齐填充。对象头部分包含了指向对象类型数据的指针。接下来通过图来理解。


对于这两种访问方式来说,各有千秋,句柄访问最大的好处就是reference中存储的是句柄地址,对象移动时候(在上一节我们通过讨论可知,在垃圾回收期间,不同的垃圾收集器在垃圾收集的时候可对存活的对象进行“压缩”移动),就只改变句柄中的指向对象实例数据的指针即可。
而对于直接指针访问方式来说,最大的特点就是一个字,快。访问速度快,节省了一次指针定位的时间,虽然一次的访问时间对于现在的计算机以及虚拟机来说没有多少,但是对于java这种频繁访问对象的语言来说,积少成多之后这可是一笔不小的开销成本。三大商用虚拟机之一的,也就是咱们总是在作为参照讨论的HotSpot VM就是采用直接指针访问方式。但是不同的虚拟机会采用不同的方式来进行对对象的访问,所以采用句柄访问方式也是很常见的。
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:790次
    • 积分:47
    • 等级:
    • 排名:千里之外
    • 原创:4篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档