YoungGC 和 FullGC 的触发条件是什么?

#Java#面试八股

YoungGC 和 FullGC 的触发条件是什么?

结论先行:Young GC 只有一个主条件——新生代 Eden 区放不下新对象;Full GC 的触发条件则有一串:老年代空间不足、晋升/担保失败、元空间扩容、显式 System.gc()、CMS 并发模式失败、G1 转移失败、堆转储请求。面试时要能按收集器分别说清,而不是笼统地讲「内存不够」。

一、Young GC 的触发

触发点说明
Eden 区满最常见;新对象分配时 Eden 无足够连续空间
TLAB 耗尽且 Eden 无法再切分线程本地分配缓冲用尽,需要新的分配区域
大对象直接在 Eden 分配失败超过 PretenureSizeThreshold 尝试直入老年代,失败则先做 Young GC

Young GC 一定会 STW,但只扫描新生代与卡表(记忆集)里的跨代引用,所以停顿短。

二、Full GC 的触发

触发点所属收集器说明
老年代空间不足全部晋升或大对象分配时无连续空间
空间分配担保失败全部Young GC 前检查老年代余量不够
晋升失败(promotion failed)Parallel、CMS存活对象要晋升但没有空间
元空间达到阈值JDK 8+MetaspaceSize 触发的首次扩容前会先做一次 Full GC
显式调用全部System.gc()、Runtime.gc()、JConsole 的「执行 GC」
CMS 并发模式失败CMS并发清理未完成老年代已满
转移失败 / Humongous 分配失败G1没有空闲 Region 可搬
jmap -dump 或 HeapDumpBeforeFullGC全部工具主动触发
分配新对象
   │ Eden 有空间?
   ├─ 是 → 分配,结束
   └─ 否 → Young GC(STW)
             │ 存活对象晋升
             ├─ 老年代有余量 → 复制到老年代,结束
             └─ 无余量 → 担保检查 → 失败则 Full GC(STW 更长)

三、按收集器区分

收集器Young GC 触发Full GC 触发
Serial / ParallelEden 满老年代不足、担保失败、System.gc()
CMSParNew 的 Eden 满老年代占用 ≥ CMSInitiatingOccupancyFraction(默认 92%)时启动并发收集;并发模式失败则 Full GC
G1Eden Region 用尽并发标记后进入 Mixed GC;转移失败或 Humongous 分配失败才 Full GC

注意 CMS 的「老年代占用达阈值」启动的是并发收集而非 Full GC,只有并发收集追不上才算 Full GC——这是 CMS 与 Parallel 最容易被混淆的点。

四、把两种 GC 都逼出来

public class TriggerDemo {
    public static void main(String[] args) throws Exception {
        // 1. Young GC:快速产生大量短命对象,Eden 很快填满
        for (int i = 0; i < 200_000; i++) {
            byte[] tmp = new byte[1024];       // 立即失效,只占 Eden
        }

        // 2. Full GC:让对象晋升并在老年代堆积
        java.util.List<byte[]> hold = new java.util.ArrayList<>();
        for (int i = 0; i < 64; i++) {
            hold.add(new byte[1024 * 1024]);  // 累计超过 -Xmx 的一半,触发老年代回收
        }

        // 3. 显式 Full GC
        System.gc();
        System.out.println("held=" + hold.size());
    }
}
# 小堆跑,几秒内即可看到 Pause Young 与 Pause Full
java -Xms64m -Xmx64m -Xmn16m -Xlog:gc* TriggerDemo

# 观察触发原因(JDK 11+)
jcmd <pid> GC.cause

五、常见追问

追问回答要点
Young GC 会清理老年代吗不会,但会把存活对象晋升进去;老年代增长过快会加速后续 Full GC
为什么元空间会触发 Full GC扩容前先尝试回收,回收不到才申请本地内存,避免无脑增长
System.gc() 到底做不做默认做;-XX:+DisableExplicitGC 后变成空操作;-XX:+ExplicitGCInvokesConcurrent 改为并发
G1 的 Mixed GC 算 Full GC 吗不算,Mixed 只回收部分老年代 Region,是 G1 的正常回收;Full 才是兜底
怎么减少 Full GC降分配速率、调大 Survivor、避免大对象、修泄漏、别让元空间无限增长

小结

Young GC 只有「Eden 满」一个主因,Full GC 是一组失败路径的集合。答题时按「收集器 + 触发条件 + 日志关键字」三层展开,比背名词扎实得多。

笔记加载中…