Java对象内存布局与访问定位

Java对象布局

         Java对象由三部分构成:对象头、实例数据、对齐补充。

(1)对象头
         对象头通常包括两部分信息:
               第一部分是与对象在运行时状态相关的信息,长度通过与操作系统的位数保持一致。包括对象的哈希值、GC分代年龄、锁状态以及偏向线程的ID等。由于对象头信息是与对象所定义的信息无关的数据,所以使用了非固定的数据结构,以便存储更多的信息,实现空间复用。因此对象在不同的状态下对象头的存储信息有所差别。
               另一部分是类型指针,即指向该对象所属类元数据的指针,虚拟机通常通过这个指针来确定该对象所属的类型(但并不是唯一方式)。
               另外,如果对象是一个数组,在对象头中还应该有一块记录数组长度的数据,因为JVM可以通过对象的元数据确定对象的大小,但不能通过元数据确定数组的长度。
(2)实例数据
          实例数据存储的是真正的有效数据,即各个字段的值。无论是子类中定义的,还是从父类继承下来的都需要记录。这部分数据的存储顺序受到虚拟机的分配策略以及字段在类中的定义顺序的影响。
(3)对齐补充:这部分数据不是必然存在的,因为对象的大小总是8字节的整数倍,该数据仅用于补齐实例数据部分不足整数倍的部分,充当占位符的作用。


对象的访问定位

        Java中的对象在堆内存中分配内存空间,引用保存在栈内存中,通过引用定位对象的具体为止通常有两种方式:

(1)句柄访问
               此方式在堆空间维护一个句柄池,对象引用中保存的是对象的句柄位置。句柄中包含各对象的实例数据和类型数据的地址信息:
在这里插入图片描述       此方式的好处是对象引用中保存的是稳定的对象句柄的地址,因为对象的移动在GC过程中是非常普遍的行为,对象的移动会导致实例数据的地址发生变化。带来的缺点就是访问效率受影响。

(2)直接指针访问:即对象引用中保存的直接的对象地址
在这里插入图片描述该方式的优点是节省了一次指针定位的开销,访问速度快。缺点是当对象地址发生变化是引用中保存的数据也需要变化。

以上内容总结自《深入理解Java虚拟机》~~~

猜你喜欢

转载自blog.csdn.net/qq_29468573/article/details/82897288