在 Java 中,垃圾回收(GC)的频率和触发条件取决于GC算法、堆内存分配、对象生命周期以及JVM参数的配置。
GC 触发条件
年轻代 GC(Minor GC / Young GC)
- Eden 区满了:当新对象分配到 Eden 区,如果 Eden 区没有足够的空间分配新对象,就会触发 Minor GC。
- Survivor 空间不足:当存活对象从 Eden 复制到 Survivor,但 Survivor 空间不够时,也可能导致 Minor GC。
- 仅回收年轻代(Young Generation),不会影响老年代(Old Generation)。
- 采用复制算法(如 Serial、Parallel、G1 的 YGC)。
- 停顿时间短,但回收频率较高。
- Minor GC 之后,存活对象可能晋升到老年代。
老年代 GC(Major GC / Old GC)
- 老年代空间不足:当对象从 Survivor 晋升到老年代,或者大对象直接进入老年代,导致老年代空间不够时,会触发 Major GC。
- G1 GC 触发 Mixed GC:G1 在一定条件下会触发回收老年代的 Mixed GC。
- 主要清理老年代(Old Generation),回收存活时间较长的对象。
- 相比 Minor GC,Major GC 的停顿时间更长,但一般回收频率较低。
- 某些 GC(如 CMS)不会 STW,而是并发执行(Concurrent Mark-Sweep)。
Full GC
- 显式调用
System.gc()(不推荐,因为 JVM 可能会忽略)。 - 老年代空间不足:当老年代没有足够空间存放新对象时,Major GC 可能变成 Full GC。
- Metaspace/元空间溢出(如类加载过多,导致
java.lang.OutOfMemoryError: Metaspace)。 - G1 GC 触发 Full GC:当 G1 发现回收无法跟上对象分配速度时,会进行 STW 的 Full GC。
- 回收整个堆(包括年轻代 + 老年代 + 元空间)。
- 停顿时间长,影响系统吞吐量和响应时间。
- 一般不希望频繁发生 Full GC,需要调优。
GC 频率的影响因素
对象分配速率
- 短生命周期对象多(临时变量、业务请求数据)→Minor GC 频繁。
- 大量大对象(如
byte[])→ 可能直接进入老年代,加速 Major/Full GC。
GC 算法
不同 GC 算法对 GC 频率的影响不同:
- Serial GC(单线程、适用于小内存) → GC 频率高,暂停时间长。
- Parallel GC(多线程 GC,吞吐量优先) → GC 频率较低,适用于高吞吐场景。
- G1 GC(区域化分代、回收预测) → 控制 GC 停顿时间,适用于大内存。
- ZGC、Shenandoah GC(低延迟 GC) → 减少 GC 影响,适用于大内存应用。