简介
Hotspot虚拟机中,Java对象在堆内存中的存储布局可分为三个部分:
- 对象头Header
- 实例数据Instance Data
- 对齐填充Padding
详情
1、对象头
Hotspot虚拟机中,对象头部分包含两类信息。
① MarkWord
用于存储对象自身的运行时数据,如GC分代年龄、哈希码、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等信息。这些运行时数据在32位和64虚拟机中分别是32位和64位,官方称其为MarkWord。
对象运行时需要存储的信息有很多,实际上超出了32、64位Bitmap结构所能记录的最大限度。但对象头中的信息是与对象本身定义的数据无关的额外存储成本,为了虚拟机的存储效率,MarkWord被设计成有动态定义的数据结构,以尽量少的存储空间记录尽可能多的信息,根据对象自身的状态复用自己的空间。
② 类型指针
对象指向它的类型元数据的指针,虚拟机通过这个指针判断它是哪个类型的实例。
并不是所有的虚拟机实现都需要在对象头中保存类型指针,即查找对象的元数据信息不一定要通过对象本身。
如果对象是一个Java数组,则还需要记录数组长度
2、实例数据
真正用于存储Java对象自身定义的数据的区域
数据内容包括:
- 从父类继承的字段
- 在该类中定义的字段
数据存储数据条件默认优先级:
- 数据从长到短的顺序存储,如longs/doubles、ints、shorts、bytes/booleans、oop。
- 在满足1的条件下,从父类中继承的字段会在子类定义的字段的前面
- 在满足1、2的条件下,按照字段在源码中定义的顺序进行存储
//虚拟机配置参数
+XX:FieldsAllocationStyle //用于配置字段存储顺序
+XX:CompactFields //用于允许子类字段插入到父类字段存储间隙中,节省存储空间
3、Padding
占位字段,Hotspot虚拟机内存管理系统要求对象起始地址必须是8B的整数倍,即任何对象的大小都应是8B的整数倍。