java对象内存布局和访问对象方式
java对象内存布局
对象头⽤于存储对象的元数据信息:
Mark Word 部分数据的⻓度在32位和64位虚拟机(未开启压缩指针)中分别为32bit和64bit,存储对象⾃身的运⾏时数据如哈希值等。Mark Word⼀般被设计为⾮固定的数据结构,以便存储更多的数据信息和复⽤⾃⼰的存储空间。
类型指针指向它的类元数据的指针,⽤于判断对象属于哪个类的实例。
实例数据存储的是真正有效数据,如各种字段内容,各字段的分配策略为longs/doubles、ints、shorts/chars、bytes/boolean、oops(ordinary object pointers),相同宽度的字段总是被分配到⼀起,便于之后取数据。
⽗类定义的变量会出现在⼦类定义的变量的前⾯。
对⻬填充部分仅仅起到占位符的作⽤
访问对象方式
当我们在堆上创建⼀个对象实例后,就要通过虚拟机栈中的reference类型数据来操作堆上的对象。现在主流的访问⽅式有两种(HotSpot虚拟机采⽤的是第⼆种):
1. 使⽤句柄访问对象。即reference中存储的是对象句柄的地址,⽽句柄中包含了对象实例数据与类型数据的具体地址信息,相当于⼆级指针。
2. 直接指针访问对象。即reference中存储的就是对象地址,相当于⼀级指针。
-
对象句柄访问
-
直接指针访问
-
访问方式对比
垃圾回收分析:⽅式一当垃圾回收移动对象时,reference中存储的地址是稳定的地址,不需要修改,仅需要修改对象句柄的地址;⽅式二垃圾回收时需要修改reference中存储的地址。
访问效率分析,⽅式⼆优于⽅式⼀,因为⽅式⼆只进⾏了⼀次指针定位,节省了时间开销,⽽这也是HotSpot采⽤的实现⽅式。