对象年龄由gc机制维护,存储于对象头mark word中(特定gc算法下),与monitor无关;monitor仅管理锁状态,不参与对象生命周期追踪。

Java中堆内存的各个分区(如年轻代的Eden、Survivor区,以及老年代)确实会跟踪对象的“存活年龄”,但这个年龄计数器并不存储在Monitor中,也不与Monitor有任何直接关联。
对象年龄的本质是GC机制的一部分
对象年龄(age)是JVM垃圾收集器(尤其是分代GC,如G1、Parallel GC、CMS等)用于判断对象是否该晋升到老年代的内部计数器:
- 每次Minor GC后仍存活的对象,其年龄加1;
- 当年龄达到阈值(如默认的15,可通过-XX:MaxTenuringThreshold设置),对象被晋升至老年代;
- 该年龄信息由GC子系统维护,通常记录在对象头(Object Header)的mark word中——但仅当mark word未被用于锁状态、hashcode等其他用途时,才复用部分位来存年龄(例如在Serial/Parallel GC中,3位用于存年龄0–15);
- G1 GC则不依赖对象头存年龄,而是通过Remembered Sets和GC日志中的age table等元数据结构在GC周期内动态追踪。
Monitor与对象锁相关,和年龄无关
Monitor是JVM实现synchronized同步机制的核心结构,每个Java对象关联一个Monitor(通过对象头的monitor pointer或lock record间接引用):
- Monitor中保存的是锁状态(无锁、偏向锁、轻量级锁、重量级锁)、持有线程、等待队列、同步队列等信息;
- 它不感知、也不存储对象的GC年龄、分配时间、是否可达等运行时生命周期信息;
- 即使对象被加锁,其年龄计数依然由GC管理,与Monitor完全解耦。
常见误解来源
混淆往往源于对对象头(Object Header)结构的不完整理解:
- 对象头包含mark word和klass pointer;
- mark word是“多用途复用字段”:在无锁状态下可能存hashcode,在偏向锁下存线程ID,在轻量级锁下存栈中锁记录地址,在GC时(特定GC算法下)才临时借用低位存年龄;
- 但这属于mark word的上下文化语义,不是Monitor的功能,也不是持久化存储——GC结束后这些位可能被重置或复用。
如何验证?
可通过以下方式确认年龄与Monitor无关:
- 使用jhsdb jmap --histo:live或-XX:+PrintGCDetails观察GC日志中的“age”分布,该信息来自GC线程,非Monitor;
- 用Unsafe.objectFieldOffset或JOL(Java Object Layout)工具查看对象头内容,可发现mark word布局随锁状态动态变化,但年龄只出现在GC相关场景的特定编码中;
- 在synchronized块中打印对象哈希码(hashCode())会触发mark word写入hash,此时年龄信息必然被覆盖——说明二者互斥,不可能共存于同一字段。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











