在HotSpot虚拟机中。对象在内存中存储的布局分为
- 对象头
- 实例数据
- 对齐填充
对象头【markword】
在32位系统下,对象头8字节,64位则是16个字节【未开启压缩指针,开启后12字节】。
markword很像网络协议报文头,划分为多个区间,并且会根据对象的状态复用自己的存储空间。
为什么这么做:省空间,对象需要存储的数据很多,32bit/64bit是不够的,它被设计成非固定的数据结构以便在极小的空间存储更多的信息.
假设当前为32bit,在对象未被锁定情况下。25bit为存储对象的哈希码、4bit用于存储分代年龄,2bit用于存储锁标志位,1bit固定为0。
对象在不同状态下,markword存储的内容也不一样,如下图所示:
这其中锁标识位需要特别关注下。锁标志位与是否为偏向锁对应到唯一的锁状态。锁的状态分为四种无锁状态
、偏向锁
、轻量级锁
和重量级锁
,不同状态时对象头的区间含义,如图所示。
HotSpot底层通过markOop实现Mark Word,具体实现位于markOop.hpp
文件。
markOop中提供了大量方法用于查看当前对象头的状态,以及更新对象头的数据,为synchronized锁的实现提供了基础。[比如说我们知道synchronized锁的是对象而不是代码,而锁的状态保存在对象头中,进而实现锁住对象]。实例数据
存放对象程序中各种类型的字段,不管是从父类中继承下来的还是在子类中定义的。
分配策略:相同宽度的字段总是放在一起,比如double和long.
引用类型占用空间:32位系统 -> 4字节;64位系统 -> 8字节
由于HotSpot规定对象的大小必须是8的整数倍,对象头刚好是整数倍,如果实例数据不是的话,就需要占位符对齐填充。