HotSpot VM 中对象的内存分析

2020-10-27

对象的内存布局

HotSpot VM 中,对象在堆内存中的存储布局分为:

  • 对象头(Header)

  • 实例数据(Instance Data)

  • 对齐填充(Padding)

 

1、对象头

  • Mark Word,对象运行时数据,动态定义位数据。包含 HashCode、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等。32 位和 64 位的 VM 里 Mark Word 的长度分别 32 bit 和 64 bit。

  • 类型指针,对象指向所属 class 的元数据的指针,32 位 VM 4 byte,64 位 VM 8 byte(-XX:+UseCompressedOops 压缩指针 4 byte)。非必需,取决 JVM 实现。

  • 数组对象必须包含长度信息,4 byte。

 

2、实例数据

  • 按分配策略和源码定义的顺序,存储对象的字段数据。

  • 8 byte:long、double

  • 4 byte:int、float、oops(Ordinary Object Pointers)

  • 2 byte:short、char

  • 1 byte:byte

  • 1 bit:boolean

 

3、对齐填充

  • 非必需,保证对象大小是 8 字节的整数倍进行填充的长度。

  • 没有特殊含义,仅占位。

 

对象的创建

new 语法创建普通 Java 对象的过程

  • 检查类是否已加载、解析、初始化,若没有则进行。

  • 为新对象分配内存。规整的内存使用指针碰撞(Bump The Pointer);不规整的内存使用列表记录可用内存的方式配分叫空闲列表(Free List)。

  • 配分内存的两种安全方式:CAS;每个线程在 Heap 中预先分配一小块内存,即本地线程分配缓存(Thread Local Allocation Buffer)。

  • 初始化分配的内存,字段设为默认零值

  • 根据 JVM 运行的情况,设置对象头信息。如类的元数据、HashCode、GC 分代年龄、偏向锁...

  • 执行构造函数、字段赋值...

 

对象的访问定位

通过栈上的 reference 数据定位、访问堆上的对象,两种方式:

  • 句柄访问。栈中本地变量表里的 reference 存储的是堆中句柄池中对象的句柄地址,句柄包含了对象实例数据和类型数据的地址。

  • 直接指针。栈中本地变量表里的 reference 存储的是对象数据地址,可以直接访问,少一次寻址访问速度快。

 

实例分析

ConstXiong 备案号:苏ICP备16009629号-3