前言

在HotSpot虚拟机中,对象在内存中存储的布局分为3块区域:

  1. 对象头
  2. 实例数据
  3. 对其填充

对象头

对象头中包括两部分信息:

  1. 第一部分用于存储对象自身的运行时数据,长度为32位或64位:
  1. 哈希码
  2. GC分代年龄
  3. 锁状态标志
  4. 线程持有的锁
  5. 偏向线程ID
  6. 偏向时间戳

因为对象头占用的空间比较小,所以空间不是固定的数据结构,是随着状态不同,而存储的内容不同:

存储内容

标志位

状态

指向栈中锁记录的指针

00

轻量级锁

对象哈希码、对象分代年龄

01

未锁定

偏向线程ID、偏向时间戳、对象分代年龄

01

可偏向锁

指向重量级锁的指针

10

重量级锁

空,不需要记录信息

11

GC标记

  1. 第二部分是类型指针
  • 就是对象指向它的类元数据的指针。
  • 如果对象是Java数组,在对象头中还必须有一块用于记录数组长度的数据
  • 因为数组的元数据中无法确定数组的大小。但是虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小。

实例数据

存储对象的有效信息,也就是在代码中定义的各种类型的字段。

无论是从父类继承下来的,还是在子类中定义的字段。

相同宽度的字段总是被分配到一起。

在满足这个前提的条件下,在父类中定义的变量会出现在子类之前。

当CompactFields参数值为true,那么子类之中较窄的变量也可能会插入到父类变量的空隙之中。

对齐填充

对齐填充不是必然存在的,仅仅起着占位符的作用。

HotSpot的自动内存管理系统要求对象的起始地址必须是8字节的整数倍。