对象在内存中的整体结构

在堆区中,一个对象的整体结构如下:
对象头 + 实例数据 + 对齐填充
整体结构如图所示:
Java - 对象的内存布局浅析

1、对象头解析

对象头包括内容如下:
运行时数据区(Mark word) + 类型指针(Klass word) + 数组长度记录(非数组对象没有)

在堆区,JVM需要存储大量对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段,用来增强对象的功能,这些标记字段就是在对象头中存储。

以32bit JVM为例,普通对象头的组成如下:

Object Header (64 bits)
Mark Word (32 bits) + Klass Word (32 bits)

数组对象的对象头如下

Object Header (96 bits)
Mark Word (32 bits) + Klass Word (32 bits) + array length(32bits)

(1) 运行时数据区
运行时数据区,一般也称为 " Mark Word ",是一个很重要的内存空间,内部存放了大量对该对象运行时自身的数据标识,比如:gc年龄分代、锁标志位、哈希值等等。

我们知道,对象是可以被锁的,也就是对象锁(也叫方法锁),针对一个对象实例,标识该对象实例是否具有锁,所以只能锁定当前的对象,对其他的对象实例不会产生任何影响。
而对象锁的情况,也是在Mark Word中进行标识的。

目前对象共有如下几种状态:
(1) 正常状态的对象
(2) 加了偏向锁的对象
(3) 加了轻量级锁的对象
(4) 加了重量级锁的对象
(5) 等待GC回收的对象

表1:不同状态的对象所对应的Mark Word结构(在32bit和64bit两种情况下)

Mark Word (32 bit) status
identity_hashcode:25 bit | age:4 bit | biased_lock:1 bit | lock:2 bit 正常状态的对象
thread:23 bit | epoch:2 bit | age:4 bit | biased_lock:1 bit | lock:2 bit 加了偏向锁的对象
ptr_to_lock_record:30 | lock:2 加了轻量级锁的对象
ptr_to_heavyweight_monitor:30 | lock:2 加了重量级锁的对象
lock:2 被标示为等待GC的对象
Mark Word (64 bit) status
unused:25 | identity_hashcode:31 | unused:1 | age:4 bit | biased_lock:1 | lock:2 正常状态的对象
thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 加了偏向锁的对象
ptr_to_lock_record:62 | lock:2 加了轻量级锁的对象
ptr_to_heavyweight_monitor:62 | lock:2 加了重量级锁的对象
lock:2 被标示为等待GC的对象

下面逐个分析Mark Word中各个字段的含义:
(1) identity_hashcode:标识对象的hashcode值,只有普通对象中存储;
(2) age:分代年龄,没经过一次s区的复制,该对象的age增加1;
(3) biased_lock与lock:这两个地方相互配合,共同描述一个对象锁和GC状态,见下图:

biased_lock 标识是否为偏向锁 lock 锁状态 对应状态
0 01 普通对象
1 01 对象具有偏向锁
无此字段 00 对象具有轻量级锁
无此字段 10 对象具有重量级锁
无此字段 11 GC标记

可以从上表中看到,lock的2bit和biased_lock的1bit,完成了对对象5种状态的描述,其中biased_lock用来区分了是否为偏向锁。

相关文章:

  • 2021-09-29
  • 2018-12-04
  • 2021-12-13
  • 2021-04-11
  • 2021-09-08
  • 2020-02-05
  • 2021-05-08
  • 2018-04-15
猜你喜欢
  • 2019-01-22
  • 2021-06-02
  • 2021-10-22
  • 2021-03-05
  • 2021-12-17
  • 2021-11-10
  • 2021-04-10
相关资源
相似解决方案