Java 对象头(Object Header)结构
Java 对象在内存中的存储布局分为三部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。其中对象头是理解 Java 锁机制、GC 等关键功能的基础。
一、对象头组成
对象头包含两部分(32位和64位系统结构不同):
1. Mark Word(标记字段)
存储对象自身的运行时数据,长度与系统位数相同(32位/64位)
2. Klass Pointer(类型指针)
指向对象元数据的指针,JVM 通过它确定对象是哪个类的实例
注意:如果开启指针压缩(-XX:+UseCompressedOops,默认开启),64位系统的 Klass Pointer 为32位
二、Mark Word 详细结构
Mark Word 在不同锁状态下会存储不同的内容:
32位虚拟机下的结构
lua
|-------------------------------------------------------|--------------------|
| Mark Word (32 bits) | State |
|-------------------------------------------------------|--------------------|
| identity_hashcode:25 | age:4 | biased_lock:1 | lock:2 | Normal |
|-------------------------------------------------------|--------------------|
| thread:23 | epoch:2 | age:4 | biased_lock:1 | lock:2 | Biased |
|-------------------------------------------------------|--------------------|
| ptr_to_lock_record:30 | lock:2 | Lightweight Locked |
|-------------------------------------------------------|--------------------|
| ptr_to_heavyweight_monitor:30 | lock:2 | Heavyweight Locked |
|-------------------------------------------------------|--------------------|
| | lock:2 | Marked for GC |
|-------------------------------------------------------|--------------------|
64位虚拟机下的结构
lua
|------------------------------------------------------------------------------|--------------------|
| Mark Word (64 bits) | State |
|------------------------------------------------------------------------------|--------------------|
| unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 | Normal |
|------------------------------------------------------------------------------|--------------------|
| thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 | Biased |
|------------------------------------------------------------------------------|--------------------|
| ptr_to_lock_record:62 | lock:2 | Lightweight Locked |
|------------------------------------------------------------------------------|--------------------|
| ptr_to_heavyweight_monitor:62 | lock:2 | Heavyweight Locked |
|------------------------------------------------------------------------------|--------------------|
| | lock:2 | Marked for GC |
|------------------------------------------------------------------------------|--------------------|
各字段说明:
- lock (2位):锁状态标志位
- 00:轻量级锁
- 01:无锁/偏向锁(通过biased_lock区分)
- 10:重量级锁
- 11:GC标记
- biased_lock(1位):是否启用偏向锁
- age(4位):对象分代年龄(GC时对象存活次数,最大15)
- identity_hashcode(31位):对象哈希码
- thread(54/23位):持有偏向锁的线程ID
- epoch(2位):偏向锁时间戳
- ptr_to_lock_record(62/30位):指向栈中锁记录的指针
- ptr_to_heavyweight_monitor(62/30位):指向重量级锁(Monitor)的指针
三、Klass Pointer(类型指针)
指向方法区中的类元数据(Class Metadata),JVM 通过它确定:
- 对象属于哪个类
- 类的完整继承结构
- 方法调用时的动态绑定
在64位系统中:
- 未开启指针压缩:64位
- 开启指针压缩(默认):32位
四、对象头大小总结
系统位数 | 配置 | Mark Word | Klass Pointer | 总头大小 |
---|---|---|---|---|
32位 | - | 32 bit | 32 bit | 64 bit |
64位 | 关闭指针压缩 | 64 bit | 64 bit | 128 bit |
64位 | 开启指针压缩(默认) | 64 bit | 32 bit | 96 bit |
五、使用 JOL 工具查看对象头
Java Object Layout (JOL) 是 OpenJDK 提供的分析工具:
java
// 添加依赖:org.openjdk.jol:jol-core
public class ObjectHeaderExample {
public static void main(String[] args) {
Object obj = new Object();
System.out.println(ClassLayout.parseInstance(obj).toPrintable());
synchronized (obj) {
System.out.println(ClassLayout.parseInstance(obj).toPrintable());
}
}
}
示例输出(64位系统,指针压缩):
python
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 # Mark Word
4 4 (object header) 00 00 00 00 # Mark Word
8 4 (object header) e5 01 00 f8 # Klass Pointer
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
六、对象头的关键作用
- 锁实现:支撑 synchronized 的偏向锁、轻量级锁、重量级锁
- GC管理:记录分代年龄、GC标记
- 对象标识:存储哈希码
- 类型系统:通过 Klass Pointer 实现运行时类型检查
理解对象头结构对于分析 Java 内存布局、性能优化和并发问题排查都有重要意义。