JVM垃圾回收按需触发,非定时执行:Eden区满触发Minor GC;老年代空间不足触发Major/Full GC;元空间或堆外内存耗尽也会触发Full GC;System.gc()仅为建议,不保证执行。

JVM 垃圾回收不是定时执行的,而是按需触发——核心原则是“内存不够用了才收”。真正决定 GC 是否启动的,是 JVM 在分配新对象时发现对应内存区域已无足够空间,此时必须先回收再分配。
新生代空间不足触发 Minor GC
绝大多数新对象都分配在新生代的 Eden 区。Eden 区通常较小(几十 MB 级),很快会被填满。一旦新对象无法放入 Eden,JVM 立即触发 Minor GC。
- 只回收新生代(Eden + Survivor),不涉及老年代
- 采用复制算法,效率高、停顿短,但频率较高
- 若 Survivor 区无法容纳存活对象,或晋升时老年代空间不足,可能升级为 Full GC
老年代空间不足触发 Major/Full GC
当对象晋升失败、大对象直接分配到老年代失败,或老年代自身使用率过高(如长期缓存积累),就会触发更重的回收。
- 常见于 Minor GC 后对象无法晋升、或显式创建大数组/大对象
- Major GC 通常伴随 Minor GC,部分收集器(如 CMS)会单独回收老年代
- 若回收后仍无法腾出足够空间,直接抛出 OutOfMemoryError: Java heap space
元空间或直接内存告警触发 Full GC
Java 8+ 使用元空间(Metaspace)存放类元数据。动态生成大量类(如 Spring AOP、反射、CGLib)、频繁加载卸载类,会导致元空间耗尽;同样,堆外内存(ByteBuffer.allocateDirect)用满也可能触发 Full GC 尝试释放资源。
- 元空间满时抛出 OutOfMemoryError: Metaspace
- 可通过
-XX:MaxMetaspaceSize限制上限,避免无限增长 - 堆外内存泄漏不易察觉,需结合 Native Memory Tracking(NMT)排查
显式调用 System.gc() 是弱提示而非指令
System.gc() 或 Runtime.getRuntime().gc() 只是向 JVM 发出建议,是否执行、何时执行完全由 JVM 决定。现代 JVM(尤其 G1、ZGC)大多忽略该调用。
- 生产环境强烈不推荐使用,干扰自动 GC 策略,可能引发不必要的 Full GC
- 可通过
-XX:+DisableExplicitGC彻底禁用显式 GC 请求 - RMI 等框架默认会调用,禁用后需确认其内存管理行为是否受影响

















