-XX:+PrintTenuringDistribution用于打印Young GC后Survivor区对象年龄分布,通过Desired survivor size、new threshold及各age行数据,可判断动态晋升、Survivor溢出强制晋升或稳定按龄晋升三种行为,并需结合PrintGCDetails等参数闭环分析。

-XX:+PrintTenuringDistribution 是 JVM 提供的一个关键诊断参数,用于打印每次 Young GC 后 Survivor 区中对象的年龄分布情况。它不直接告诉你“哪些对象晋升了”,而是通过展示各年龄档(age 1、age 2…)的对象大小和阈值,帮你反推对象是否达到 MaxTenuringThreshold、是否被提前晋升(如 Survivor 空间不足触发动态年龄计算),从而观察对象在 Survivor 区的真实晋升行为。
看懂日志核心字段:每行代表一个年龄档
开启后,每次 Young GC 日志中会出现类似这样的块:
Desired survivor size 1048576 bytes, new threshold 7 (max 15) - age 1: 1234560 bytes, 1234560 total - age 2: 456789 bytes, 1691349 total - age 3: 123456 bytes, 1814805 total
关键信息包括:
- Desired survivor size:JVM 希望保留到下次 GC 的 Survivor 对象总容量上限(基于 Survivor 空间利用率目标,通常为 Survivor 总空间的 50%)
- new threshold:本次 GC 后,新设定的晋升年龄阈值(不是固定 max,而是动态计算结果)
- age X:当前存活到第 X 次 GC 的对象大小
- total:从 age 1 累加到当前 age 的总大小
识别真实晋升行为的三个关键判断点
对象是否晋升,取决于它能否“活过”本次设定的 new threshold,而非简单数到 MaxTenuringThreshold:
-
动态阈值生效时(最常见):如果某次 GC 后
new threshold = 2,而 age 3 行存在数据(比如 123456 bytes),说明这批 age=3 的对象本该晋升,但因 Survivor 还有空间且未达阈值,所以继续留在 Survivor;反之,若total在 age 2 就已超过Desired survivor size(例如 age 1+age 2 = 1050000 > 1048576),则 age 2 及更老的对象会全部晋升——哪怕 age 2 还没到 max 阈值 -
Survivor 空间溢出强制晋升:当所有 age 档累加仍远小于 Desired survivor size,但
new threshold却突然降为 1 或 2,往往意味着 Survivor 区太小或对象存活率高,JVM 主动降低阈值以腾出空间,导致大量年轻对象“早熟”晋升 -
稳定阈值下的正常晋升:连续多次 GC 中
new threshold稳定等于MaxTenuringThreshold(如始终为 15),且age 15行持续出现非零字节数,说明对象确实经历了 15 次 GC 才晋升——这是理想中的“按龄晋升”,但生产环境较少见
配合其他参数才能闭环分析
单靠 PrintTenuringDistribution 不足以定位问题,需联动观察:
- 加上 -XX:+PrintGCDetails -Xloggc:gc.log,确认每次 Young GC 是否伴随 Promotion Failure(晋升失败)、是否触发 Full GC
- 用 -XX:+PrintAdaptiveSizePolicy 查看 JVM 是否在动态调整 SurvivorRatio、tenuring threshold,避免误判是配置问题还是业务对象生命周期异常
- 结合堆转储(jmap -dump)或 Arthas `vmtool --action getInstances` 抽样 age 较高的对象,验证是否为缓存类、连接池、长生命周期 DTO 等合理存活对象
典型异常模式与应对提示
以下日志模式值得警惕:
- “new threshold”逐轮下降(如 7→4→2→1):Survivor 区持续装不下,对象被迫快速晋升,易引发老年代压力上升 → 调大 -XX:SurvivorRatio 或 -Xmn,或检查是否存在阶段性对象堆积
- age 1 占比长期 >80%,age 2+ 几乎为 0:对象要么秒死,要么“一步登天”,说明 Survivor 形同虚设 → 检查是否 SurvivorRatio 设置过大(如 64),导致 Survivor 空间过小
- Desired survivor size 接近 0 或反复为 0:JVM 认为 Survivor 不值得保留任何对象,直接全量晋升 → 往往伴随 -XX:-UseAdaptiveSizePolicy 或 Survivor 区被压缩至极小

















