对象的内存布局
在HotSpot虚拟机中,对象在内存中的存储布局可以划分为三个区域:对象头,实例数据,对齐填充。
对象头包括两部分信息:第一部分用于存储对象自身的运行时数据,如哈希码,GC分代年龄,锁状态标志等。对象头的另一部分是类型指针,即对象指向向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
实例数据部分是对象真正存储的有效信息,也是代码中所定义的各种类型字段的内容。
对齐填充并不是一定存在的,它仅仅起着占位符的作用,这是由于HotSpot VM规定对象的起始地址必须是以8字节的整数倍,也就是说对象的大小必须是8字节的整数倍。因此当实例的数据部分没有对齐的话,就会进行对齐填充。
对象的访问定位
java程序需要通过栈上的reference数据来操作堆上的具体对象。对象的访问方式也是有虚拟机的实现所决定的。目前主流的访问方式有:使用句柄和直接指针两种。
使用句柄访问,Java堆会分配一块内存来作为句柄池,reference中存储的就是对象的句柄地址。
使用指针直接访问,Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址。
使用句柄来进行访问的好处就是reference中存储的是稳定的句柄地址,在对象被移动时,只会改变对象中的实例数据指针,而reference本身不需要改变。指针直接访问的优势就是速度快。