You said:
对象头里面存了什么信息?
ChatGPT said:
ChatGPT
在 Java 中,对象头(Object Header)是每个对象在内存中存储的额外信息,它包含了一些重要的元数据,用于管理和操作对象。这些信息在 Java 虚拟机(JVM)的垃圾回收、同步和哈希码计算等功能中起到关键作用。
1. 对象头的组成
Java 对象在内存中由两部分组成:
- 对象头(Object Header)
- 实例数据(Instance Data)
对象头通常包含两个部分:
- Mark Word
- Class Metadata Address
1.1 Mark Word
Mark Word
是对象头中的一部分,包含了与对象状态相关的元信息。它是一个多用途的字段,会根据对象的不同状态存储不同的信息。
在 32 位和 64 位的 JVM 中,Mark Word
的大小分别为 32 位和 64 位。
- 在不同状态下,
Mark Word
的内容如下:状态Mark Word
存储的内容未锁定状态哈希码(HashCode)、GC 年龄、分代信息偏向锁状态线程 ID、偏向时间戳、锁标志位轻量级锁状态指向栈中锁记录的指针重量级锁状态指向监视器(Monitor)的指针GC 标记状态GC 标记标识 - 详细信息:
- 哈希码(HashCode):如果调用了对象的
hashCode()
方法,Mark Word
会存储对象的哈希码。 - GC 年龄:对象在堆中经过多少次 Minor GC,最多 15 次(在默认的情况下,标记字段用于存储 GC 年龄)。
- 偏向锁标记:当对象处于偏向锁状态时,
Mark Word
会存储偏向锁的线程 ID 和偏向时间戳。 - 轻量级锁:当对象进入轻量级锁状态时,
Mark Word
会存储指向线程栈中锁记录的指针。 - 重量级锁:当对象进入重量级锁状态时,
Mark Word
会存储指向操作系统级别的监视器锁的指针。
- 哈希码(HashCode):如果调用了对象的
1.2 Class Metadata Address(类型元数据地址)
- 类型指针:
Mark Word
后面紧接着的是一个类型指针,指向对象对应的类的元数据(即对象所属的类的Class
对象)。 - 用途:该指针用于标识对象的类型,帮助 JVM 确定对象的结构、方法和字段等信息。
2. 对象头的用途
2.1 同步机制
- 在 Java 中,
synchronized
关键字依赖于对象头中的Mark Word
进行加锁和解锁。- 偏向锁:如果对象处于偏向锁状态,
Mark Word
中会存储偏向锁的线程 ID。如果当前线程与偏向锁的线程一致,则可以直接进入临界区。 - 轻量级锁:在轻量级锁下,
Mark Word
会存储指向线程栈中锁记录的指针。通过 CAS 操作,多个线程可以同时竞争同一个对象的锁,而不会导致重量级锁的获取。 - 重量级锁:当轻量级锁竞争失败时,JVM 会将锁升级为重量级锁。此时,
Mark Word
会存储指向重量级锁(OS 监视器锁)的指针。
- 偏向锁:如果对象处于偏向锁状态,
2.2 哈希码计算
- 当对象的
hashCode()
方法被调用时,JVM 会将对象的哈希码存储在Mark Word
中,以便后续快速获取哈希码。
2.3 GC 标记
- 在垃圾回收过程中,
Mark Word
用于存储 GC 标记,标识对象是否存活。这对于标记-清除算法、标记-整理算法和分代收集算法等垃圾回收机制至关重要。
3. 对象头的优化策略
3.1 偏向锁
- JVM 在对象头中实现了一种称为偏向锁的优化策略。偏向锁是为了减少同一线程多次获得锁时的开销。当一个对象首次被某个线程加锁时,该线程会将对象头中的锁标记置为偏向锁,并记录线程 ID。
- 适用场景:偏向锁适用于绝大多数情况下的无竞争加锁场景,可以大幅度提升性能。
- 限制条件:如果有多个线程同时竞争偏向锁,偏向锁会被撤销,升级为轻量级锁。
3.2 轻量级锁
- 轻量级锁是通过 CAS 操作将
Mark Word
中的指针替换为线程栈中的锁记录来实现的。它用于减少无锁竞争情况下的加锁和解锁开销。
3.3 重量级锁
- 当轻量级锁发生锁竞争时,锁会升级为重量级锁。重量级锁会导致线程阻塞和唤醒,开销较大。
4. 对象头结构的内存布局
4.1 32 位虚拟机中的对象头
- 在 32 位虚拟机中,对象头的
Mark Word
占 32 位(4 字节),类型指针占 4 字节,总计 8 字节。
4.2 64 位虚拟机中的对象头
- 在 64 位虚拟机中,对象头的
Mark Word
占 64 位(8 字节),类型指针占 8 字节,总计 16 字节。 - 注意:JVM 在默认情况下会启用指针压缩(Compressed Oops),将类型指针压缩为 4 字节,以节省内存。
5. 总结
- 对象头是 JVM 对象管理的核心,包含了锁信息、GC 信息、哈希码和类指针等元数据。
- 在并发、垃圾回收和哈希码计算中起到关键作用,是 JVM 实现各种优化策略的重要基础。
- 了解对象头的原理有助于理解 Java 的同步机制、垃圾回收机制以及内存布局等关键特性。