真实面经题目 · 原创解析
Java 的 GC 机制是怎样实现的?
这题考察对象存活判定、分代回收、GC 算法和收集器取舍,还会延伸到分配晋升、停顿和 GC 日志排查。
真实面经题目 · 原创解析
这题考察对象存活判定、分代回收、GC 算法和收集器取舍,还会延伸到分配晋升、停顿和 GC 日志排查。
Java GC 先从 GC Roots 做可达性分析,判断哪些对象仍被栈、本地方法、静态字段、常量或 JNI 引用间接到达。对象通常优先在 TLAB/Eden 分配,Minor GC 后存活对象进入 Survivor 并随年龄增长晋升老年代,大对象或空间不足可能直接进入老年代。回收算法包括复制、标记清除、标记整理;收集器则在吞吐、停顿、内存占用和实现复杂度之间取舍,例如 Parallel 偏吞吐,G1 用 Region 控制停顿目标,ZGC 更强调低停顿。
主流 JVM 不靠引用计数,而是从 GC Roots 遍历引用图。能到达的对象保留,不可达对象成为回收候选。循环引用只要整体不可达,也可以被回收。
新对象通常先进线程本地 TLAB 或 Eden。Minor GC 时,存活对象复制到 Survivor,年龄增长到阈值或 Survivor 放不下时晋升 Old;超大对象可能绕过新生代直接进入老年代。
复制算法快但需要空闲空间,适合新生代;标记清除会留下内存碎片;标记整理能减少碎片但要移动对象,成本更高。老年代对象存活率高,不能简单套新生代策略。
Parallel 追求吞吐,适合批处理;G1 把堆拆成 Region,通过 remembered set 和 mixed GC 控制停顿;ZGC/Shenandoah 把更多阶段并发化,适合低延迟但有额外读写屏障成本。
频繁 Young GC 多半与分配速率、对象生命周期有关;Full GC 常见于老年代不足、元空间不足、晋升失败或显式 `System.gc`。线上要结合 GC 日志、堆 dump、分配热点和接口延迟判断。
它难处理循环引用,并且每次引用变化都要维护计数。可达性分析能统一判断从 Roots 出发是否还可访问。
Minor GC 主要回收新生代;Major GC 常指老年代回收;Full GC 通常涉及整个堆甚至元空间,停顿风险更高,具体含义还要看收集器和日志口径。
G1 把堆拆成 Region,按回收收益选择部分 Region 做 mixed GC,并通过停顿目标估算每轮工作量,但停顿目标不是绝对保证。
泄漏是对象仍被引用导致无法回收,堆占用持续上升;GC 频繁可能只是分配速率高或对象生命周期短,需要用日志和堆 dump 区分。