[面试题] G1 如何精确控制 STW?为什么 JDK9 之后成为默认垃圾回收器?
📖 版块 A:知识讲解版 (温故知新)
-
G1 的核心设计:
- 不再把堆物理上简单切成固定的新生代和老年代。
- 而是把整个堆切成很多大小相等的 Region。
- 每个 Region 可以在逻辑上扮演 Eden、Survivor、Old 等角色。
-
G1 如何控制停顿时间:
- 维护每个 Region 的回收收益估算。
- 按“垃圾最多、回收最划算”的思路优先选择回收集合。
- 结合暂停时间预测模型,尽量在给定停顿目标内完成回收。
- 通过 Region 粒度回收,避免一次性处理过大连续空间。
-
为什么成为默认收集器:
- 兼顾吞吐量和低停顿。
- 解决 CMS 的碎片问题。
- 对大堆场景更友好。
- 可预测性更强,更适合作为通用默认方案。
🎤 版块 B:面试实战版 (高手逐字稿)
Q:G1 如何精确控制 STW?为什么 JDK9 之后成为默认垃圾回收器?
💬 高手逐字稿:
G1 之所以叫 Garbage First,重点不在名字酷,而在于它回收时真的会优先挑那些“最值得回收”的区域下手。
传统分代收集器更像是按照固定物理分区工作,比如新生代一块、老年代一块。而 G1 则把整个堆拆成了很多大小相等的 Region。这些 Region 逻辑上可以扮演 Eden、Survivor、Old 等角色,但物理上不再是死板的一整块。
这套设计的好处是,G1 每次回收时不需要面对“一整块巨大的老年代”,而是可以挑选一部分 Region 来做回收。
那它怎么控制 STW 呢?核心有两点。
第一,按收益挑 Region。G1 会统计每个 Region 里的垃圾量和预计回收成本,优先挑那些回收性价比最高的区域。
第二,停顿预测模型。G1 允许你给出一个目标停顿时间,比如 MaxGCPauseMillis=200。它会根据以往统计数据去估算:“如果我这次选这些 Region,理论上大概会停多久。” 然后尽量把本次回收工作量控制在这个目标附近。
这也是为什么我们说 G1 的停顿不是绝对精准保证,而是尽量可预测、尽量可控。
至于为什么 JDK 9 之后它会成为默认收集器,核心原因也很直接:
- 比 CMS 更通用;
- 能解决碎片问题;
- 对大堆更友好;
- 停顿可预测性更好;
- 在吞吐和延迟之间平衡得更适合做默认选项。
所以如果一句话总结:G1 成为默认,不是因为它在所有维度都最强,而是因为它在主流通用场景下最均衡。
最后更新于: