1. 对象头:Java世界的身份证
每个Java对象在内存中都有个"身份证"——对象头(Object Header)。这个看似简单的数据结构,却承载着JVM运行时的核心信息。就像现实中的身份证记录着个人基本信息一样,对象头存储着对象的类型、锁状态、GC年龄等关键元数据。
我第一次注意到对象头的重要性是在排查一个高并发场景下的性能问题时。通过JOL(Java Object Layout)工具打印出的对象内存布局,发现对象头在不同锁状态下会发生变化,这才理解为什么锁升级会影响对象的内存占用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 对象头结构全解析
2.1 32位与64位系统的差异
在32位JVM中,对象头通常占用8字节(64位),包含:
- Mark Word(4字节):存储对象运行时数据
- Klass Pointer(4字节):指向类元数据的指针
而在64位JVM中,开启指针压缩(默认开启)时:
- Mark Word(8字节)
- 压缩后的Klass Pointer(4字节)
- 对齐填充(4字节)
提示:使用-XX:+UseCompressedOops可开启指针压缩,这是JDK6 update23后的默认行为
2.2 Mark Word的七十二变
Mark Word是对象头中最灵活的部分,其内容会根据对象状态动态变化。以下是HotSpot虚拟机中的典型布局:
| 锁状态 | 25bit | 4bit | 1bit(是否偏向锁) | 2bit(锁标志位) |
|---|---|---|---|---|
| 无锁 | hashCode | 分代年龄 | 0 | 01 |
| 偏向锁 | 线程ID+Epoch | 分代年龄 | 1 | 01 |
| 轻量级锁 | 指向栈中锁记录的指针 | 00 | ||
| 重量级锁 |
