在HotSpot虚拟机中。对象在内存中存储的布局分为

  • 对象头
  • 实例数据
  • 对齐填充

    对象头【markword】

    在32位系统下,对象头8字节,64位则是16个字节【未开启压缩指针,开启后12字节】。
    markword很像网络协议报文头,划分为多个区间,并且会根据对象的状态复用自己的存储空间。
    为什么这么做:省空间,对象需要存储的数据很多,32bit/64bit是不够的,它被设计成非固定的数据结构以便在极小的空间存储更多的信息.
    假设当前为32bit,在对象未被锁定情况下。25bit为存储对象的哈希码、4bit用于存储分代年龄,2bit用于存储锁标志位,1bit固定为0。
    对象在不同状态下,markword存储的内容也不一样,如下图所示:
    image.png
    这其中锁标识位需要特别关注下。锁标志位与是否为偏向锁对应到唯一的锁状态。锁的状态分为四种无锁状态偏向锁轻量级锁重量级锁,不同状态时对象头的区间含义,如图所示。
    image.png
    HotSpot底层通过markOop实现Mark Word,具体实现位于markOop.hpp文件。
    markOop中提供了大量方法用于查看当前对象头的状态,以及更新对象头的数据,为synchronized锁的实现提供了基础。[比如说我们知道synchronized锁的是对象而不是代码,而锁的状态保存在对象头中,进而实现锁住对象]。

    实例数据

    存放对象程序中各种类型的字段,不管是从父类中继承下来的还是在子类中定义的。
    分配策略:相同宽度的字段总是放在一起,比如double和long.
    引用类型占用空间:32位系统 -> 4字节;64位系统 -> 8字节
    由于HotSpot规定对象的大小必须是8的整数倍,对象头刚好是整数倍,如果实例数据不是的话,就需要占位符对齐填充。