minor gc日志核心看三点:触发原因(如allocation failure)、新生代内存变化(eden+s0/s1清理情况)、stw耗时(通常应<10ms);它仅反映新生代回收,不涉及老年代,异常高频或高耗时往往指向新生代过小、对象暴增或survivor配置失衡。

Minor GC 日志是分析 JVM 内存行为最常接触的部分,核心看三点:触发原因、回收前后内存变化、耗时。它反映的是新生代(Eden + 一个 Survivor)的清理情况,不涉及老年代。
看触发原因:括号里那个关键词很关键
日志开头类似 [GC (Allocation Failure) 或 [GC (Ergonomics) 这样的括号内容,说明本次 Minor GC 是为什么发生的:
- Allocation Failure:最常见,表示 Eden 区没空间给新对象分配了,这是正常触发条件
- Ergonomics:JVM 自适应策略主动调整堆结构(比如动态扩容 Eden),不是内存真不够,但可能暴露配置不合理
-
System:代码里调用了
System.gc(),应排查并避免
看内存变化:中括号内外要分开理解
典型格式:[PSYoungGen: 5986K->696K(8704K)] 5986K->704K(9216K)
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
-
中括号内(
PSYoungGen: 5986K->696K(8704K)):只看新生代。5986K 是 GC 前新生代已用内存,696K 是 GC 后剩余,8704K 是新生代总容量(含 Eden + 一个 Survivor) -
中括号外(
5986K->704K(9216K)):看整个堆(新生代 + 老年代)。这里 9216K 是堆总大小,但注意——它 ≈ 新生代总大小 + 老年代当前已用大小,不是老年代总容量 - 如果回收后新生代“剩余”接近 0(如
->0K),说明回收干净;如果回收后仍很高(比如->5000K),可能是 Survivor 太小或对象晋升过快
看 Survivor 配置是否合理
Minor GC 后存活对象会进入 Survivor 区。若 Survivor 空间长期紧张,对象会直接晋升老年代,加重老年代压力。
- 日志中不直接显示 Survivor 使用量,但可通过
-XX:+PrintGCDetails配合jstat -gc观察 S0/S1 使用率 - 常见问题:Survivor 区仅几 MB(如案例中只有 4MB),远低于实际需求,根源常是未显式设置
-XX:SurvivorRatio,导致 JVM 自适应分配失衡 - 建议值:Eden:S0:S1 = 8:1:1 对多数应用较稳,即
-XX:SurvivorRatio=8
看耗时和频率:判断是否异常
末尾的 0.0139308 secs 是本次 GC 实际暂停时间(STW),括号里的 [Times: user=0.05, sys=0.01, real=0.01] 可辅助判断是否受系统资源影响。
- 单次 Minor GC 通常在 10ms 内属正常;超过 50ms 要警惕(尤其在低延迟场景)
- 频率比耗时更值得关注:1 秒内多次 Minor GC,大概率是新生代太小或对象创建过快
- 结合业务流量看趋势——突增的 Minor GC 频率,往往对应某段代码上线或接口压测










