应根据对象实际存活轮次调整maxtenuringthreshold,优先设为5并结合gc日志、jstat监控及对象大小分析动态优化,避免默认15导致晋升不合理。

直接看对象在Survivor区里“活了几轮”,比单纯调大年轻代更有效。
用-XX:+PrintGCDetails + -XX:+PrintGCTimeStamps打点存活行为
开启详细GC日志后,每次Minor GC输出会包含每轮晋升对象的年龄分布。关键字段是age和bytes,例如:
-
[Age: 1: 124560 bytes, 2: 89232 bytes, 3: 45104 bytes]表示当前Survivor中,1岁对象占124KB、2岁占89KB、3岁占45KB - 持续采集多轮GC日志,可统计各年龄档对象占比趋势,识别“卡在S0/S1反复复制但不晋升”的异常滞留现象
配合-XX:MaxTenuringThreshold控制晋升临界点
默认阈值是15,但实际业务中多数短生命周期对象在3~5轮GC后就该晋升。建议:
- 先设为
-XX:MaxTenuringThreshold=5,观察老年代晋升速率和Full GC频率 - 若老年代增长过快,说明部分对象被误提前晋升,可逐步调高到7或8
- 若Survivor区长期堆积大量age=5的对象,说明它们本该晋升却因空间不足被滞留——这时要检查SurvivorRatio是否过小
用jstat -gc实时抓取代数分布快照
对运行中的交易系统,执行:
-
jstat -gc <pid> 1000 10</pid>每秒输出10次GC统计 - 重点关注
S0C/S1C(Survivor容量)、S0U/S1U(已用空间)及YGC(Minor GC次数)的联动变化 - 当
S0U持续接近S0C且YGC频次升高,说明对象在Survivor区“挤不下”,正在触发提前晋升或GC压力上升
结合对象大小与分配模式反推代数合理性
超大并发交易系统中,订单、支付等核心对象往往固定结构、大小稳定。例如一个订单POJO约1.2KB:
- 若Eden区设为1.5GB,理论单次可分配约120万个订单对象
- 若实测每秒创建80万订单,Eden在1~2秒填满,对应Minor GC间隔应为1~2秒
- 此时若多数对象在第2轮GC后即晋升,说明代数阈值设为2更匹配实际生命周期,而非盲目沿用默认15










