对象的内存布局及访问定位
1.对象头
a.存储对象自身的运行时数据
如哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等,这部分数据的长度再32位和64位的虚拟机(未开启压缩指针中分别为32 bit 和 64 bit),官方称他为"Mark Word"
Mark Word 被设计成一个非固定的数据结构以便在极小的空间存储尽量多的信息
b.对象执行它的类元数据指针
虚拟机通过这个指针来确定这个对象是哪个类的实例
如果对象是一个Java 数组,那再对象头中还必须有一块用于记录数组长度的数据,虚拟机可通过普通Java对象的元数据信息确定Java 对象的大小,从数组的元数据中无法确定数组的大小
2.实例数据
实例数据是对象真正的存储的有效信息,也是在程序代码中所定义的各种类型的字段内容(从父类继承,自己定义),都需记录
这部分的存储顺序会受到虚拟机分配策略参数和字段在Java源码中定义顺序的影响
3.对齐填充
并不是必然存在,仅仅启着占位符的作用,因为HotSpot VM 的自动内存管理系统要求对象的起始地址必须是8字节整数倍
目前主流的对象访问方式有两种:1.使用句柄;2.直接指针
1.使用句柄
Java 堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址
2.使用指针访问
Java 堆对象的布局中就必须考虑如何防止访问类型数据相关信息,而reference 中存储的直接就是对象地址
使用句柄访问,优点是稳定,当对象被移动,只会改变句柄中的实例数据指针,缺点是速度慢
使用直接指针访问,优点是速度快,缺点是不稳定,对象移动,指针就被改变了