Minor GC 仅由 Eden 区空间不足触发,与 Survivor、老年代、元空间无关;Full GC 则由老年代连续空间不足、元空间超限、显式调用 System.gc() 或晋升担保失败任一条件触发。

Minor GC 和 Full GC 的触发条件根本不同——不是“堆越满越容易触发”,而是各自有明确、独立的判定逻辑。搞清这一点,才能避免误判 GC 问题根源。
Minor GC:只看 Eden 区有没有空间
它不关心老年代、不看 Survivor 是否快满、也不管元空间用了多少。唯一主因就是:新对象要分配进 Eden,但 Eden 剩余空间不够。
- 哪怕 Survivor 还空着 90%,Eden 一满就立刻触发
- TLAB 分配失败后,回退到 Eden 全局分配仍失败 → 同样触发
- 大对象尝试直接进老年代失败时,JVM 会先 Minor GC 试试能不能腾出空间再晋升;如果还是失败,才走 Full GC
Full GC:只要任一关键区域告急就启动
它不是“等整个堆满了才动”,而是老年代、元空间、显式调用、担保失败中任意一个条件满足,就可能触发。
- 老年代连续空间不足:比如 Minor GC 后要晋升的对象总大小 > 老年代当前最大连续空闲空间
- 元空间超限:-XX:MaxMetaspaceSize 设置过小,或大量动态类(CGLib、AOP、热部署)持续加载未卸载
- 显式调用 System.gc():代码里写了这句,且没加 -XX:+DisableExplicitGC
- 晋升担保失败:Minor GC 前检查发现,老年代剩余空间
- 收集器退化:CMS 发生 Concurrent Mode Failure,G1 Mixed GC 跟不上分配速度,都会降级为 Full GC
一个常被误解的关键点:Minor GC 不会导致 Full GC,但可能暴露 Full GC 的诱因
比如对象年龄到了、Survivor 放不下、大对象要晋升……这些本身不触发 Full GC,但会让对象涌向老年代。一旦老年代扛不住,下一次 Minor GC 前的担保检查就会失败,直接拉 Full GC 出来救场。
所以频繁 Full GC 往往不是“老年代突然变小了”,而是年轻代配置不合理(如 Survivor 太小、晋升阈值太低)或应用行为异常(如大量短命大对象、ClassLoader 泄漏)长期积累的结果。

















