gc日志是容量规划最直接依据,需据老年代水位定堆下限、依minor gc效率调新生代大小、用gc频率与停顿校验并发能力、借晋升分布预判扩容节奏。

GC 日志是容量规划最直接、最真实的依据,不是靠预估或经验值拍板,而是用运行时数据说话。它能告诉你应用实际吃多少内存、对象怎么分布、回收压力在哪,从而避免堆配太大浪费资源,或配太小引发频繁停顿。
看老年代长期占用率定堆下限
如果 GC 日志显示:Full GC 前老年代稳定在 1.8GB~2.0GB,且每次 Full GC 后能释放到 200MB 以下,说明业务高峰期老年代真实水位约 2GB。这时 -Xms 和 -Xmx 就不应低于 2.5GB(留 20%~25% 安全余量),否则容易因浮动垃圾或晋升波动触发意外 Full GC。
反例:日志里老年代长期维持在 3.5GB/4GB(87% 占用),还硬设 -Xmx=4g —— 这已逼近临界,稍有流量上涨或对象生命周期延长,立刻触发频繁 Full GC。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
从 Minor GC 回收效率反推新生代合理大小
观察连续 10 次 Minor GC 的日志片段:
- Eden 区每次分配前都接近打满(如 980M/1000M),GC 后清空到 0~5M → 说明新生代够用,没浪费;
- 但 Survivor 区每次 GC 后存活对象猛增,且很快出现 to-space exhausted 或大量对象直接晋升(Old 区单次涨 300MB+)→ 说明 Eden 太大、Survivor 相对太小,或对象存活时间略长,需调大 -Xmn 或减小 -XX:SurvivorRatio;
- 若 Eden 总是只用到 300M 就触发 GC,且回收后 Survivor 几乎为空 → 新生代明显过大,白白占堆,应缩小以腾出空间给老年代或降低 GC 扫描开销。
用 GC 频率与停顿时间校验并发能力边界
容量规划不止看内存峰值,更要看单位时间内的 GC 负载是否可持续:
- 压测中每秒 500 QPS 时,Young GC 频率达 40 次/秒、平均耗时 35ms → 单机吞吐已达 GC 瓶颈,再加压只会让停顿堆积、响应毛刺增多;
- 同一 QPS 下,若 GC 频率仅 8 次/秒、YGC 平均 12ms,且老年代月增长<100MB → 说明当前堆配置和机器规格尚有余量,可支撑更高流量或横向扩容更从容;
- 特别注意 Mixed GC(G1)或 ZGC 停顿的稳定性:若 99 线停顿从 10ms 跳到 80ms,往往意味着老年代碎片化或并发标记滞后,此时即使内存未满,也需提前扩容节点或调整 InitiatingHeapOccupancyPercent。
结合对象晋升行为预判扩容节奏
启用 -XX:+PrintTenuringDistribution 后,关注日志中 age=1、age=2 的对象占比:
- 若 age=1 对象占 Survivor 总量 60% 以上,且持续晋升 → 说明大量对象“活过一轮就死”,但因 Survivor 不足被迫早进老年代,这不是容量问题,而是代际比例失衡,调优比扩容更有效;
- 若 age≥6 的对象占比稳定上升,且老年代对应增长平缓 → 表明业务对象天然生命周期较长(如会话缓存、聚合报表),此时扩容应优先考虑老年代预留空间,而非简单堆翻倍;
- 若某次发布后 age=15(最大阈值)对象激增,且老年代增速加快 → 很可能引入了长生命周期对象或静态集合泄漏,这时扩容只是掩盖问题,必须先代码归因。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










