核心在于让对象在新生代内自然消亡,避免过早晋升老年代引发full gc;需结合gc日志分析对象生命周期、调整新生代占比与晋升阈值、选用匹配业务的回收器,并杜绝system.gc()等干扰行为。

合理利用 GC 回收周期,核心在于理解对象生命周期与代际晋升规律,让大多数对象在新生代内自然消亡,避免过早进入老年代引发代价更高的 Full GC。
看清对象“活多久”再分配空间
新对象默认进入 Eden 区,95% 以上会在一次 Minor GC 中被回收。若观察到 Survivor 区长期有大量对象堆积、或对象频繁在两次 Minor GC 间就晋升到老年代(可通过 -XX:+PrintGCDetails 日志中的 “age” 字段确认),说明新生代空间偏小或晋升阈值过低。
- 适当增大新生代占比(如 -XX:NewRatio=2 表示新生代:老年代 = 1:2)
- 检查并调整晋升年龄阈值(-XX:MaxTenuringThreshold,默认 15,但多数业务设为 4–6 更合理)
- 避免人为调用 System.gc() 或使用 finalize(),它们会干扰自然回收节奏
让老年代“少干活”,专注存真正长寿对象
老年代触发 GC(如 CMS 或 G1 的并发标记、Full GC)开销大、停顿明显。应确保只有经多次验证仍存活的对象才晋升过去。
- 监控老年代占用增长速率:若 Minor GC 后老年代持续缓慢上涨,可能是内存泄漏或缓存未清理
- 避免大对象直接分配到老年代(如超过 -XX:PretenureSizeThreshold 的数组),除非明确需要长生命周期
- 对缓存类场景,优先用 SoftReference 或 WeakReference,让 GC 在压力下自动释放
匹配业务节奏选择回收器与目标
GC 周期不是越短越好,而是要与业务请求模型对齐。高并发短事务系统适合低延迟策略;批处理任务则更看重吞吐量。
- Web 服务类应用:启用 G1(-XX:+UseG1GC)并设置 -XX:MaxGCPauseMillis=200,让 JVM 自动调节回收频率和范围
- 后台计算任务:选用 Parallel GC(-XX:+UseParallelGC),以吞吐优先,接受稍长但可控的停顿
- 超低延迟要求(如金融交易):评估 ZGC(-XX:+UseZGC),它将停顿控制在 10ms 内,且不随堆大小线性增长
用数据驱动每一次调整
不看日志的调优等于盲调。必须开启 GC 日志并定期分析,重点关注三项:
- Minor GC 频率:每秒超过 1–2 次需警惕 Eden 过小或对象创建过快
- 老年代晋升总量:单次 Minor GC 晋升量接近几百 MB,说明新生代已无法承载对象生命周期
- GC 后老年代剩余空间:若长期高于 70%,可能面临并发模式失败(CMS)或 Mixed GC 压力过大(G1)











