G1垃圾回收器通过将堆划分为固定大小的Region并实施增量式回收与优先级调度,实现可预测的停顿时间目标;每个Region可动态承担Eden、Survivor或Old角色,回收时按“垃圾占比高、收益大、RSet更新少”选取CSet,结合Remembered Set精准处理跨Region引用,Mixed GC则分批回收新老代Region以避免Full GC。

G1 垃圾回收器通过将堆划分为固定大小的 Region(区域),并结合 增量式回收 和 优先级调度,实现可预测的停顿时间目标。它不追求一次回收全部垃圾,而是每次只处理一部分 Region,从而把 GC 停顿控制在用户设定的期望值内(如 -XX:MaxGCPauseMillis=200)。
Region 是 G1 堆管理的基本单位
G1 将整个 Java 堆划分为多个大小相等的连续内存块(默认 1MB~32MB,由堆总大小自动推算,必须是 2 的幂)。每个 Region 独立管理,可动态扮演 Eden、Survivor 或 Old 区角色——不再有物理上的年轻代/老年代边界,只有逻辑角色。这种设计让回收范围变得“可切分”,为停顿可控打下基础。
回收过程按“价值+成本”动态选择 Region
G1 不扫描整堆,而是维护一个已知垃圾量(即“可回收空间”)的 Region 排序列表(Remembered Sets 配合 RSet 卡表快速定位跨 Region 引用)。每次 GC 时:
- 根据暂停时间目标估算本次最多能花多少时间
- 按“垃圾占比高、回收收益大、记忆集更新少”的优先级,挑选一批 Region 组成 Collection Set(CSet)
- 仅对 CSet 中的 Region 执行复制(Evacuation)或清理,其余 Region 完全不动
Remembered Set(RSet)保障跨 Region 引用的准确性
每个 Region 都维护一个 RSet,记录其他 Region 中指向本 Region 的引用(例如:Old 区对象引用了 Eden 区对象)。GC 扫描 CSet 时,只需检查对应 RSet,无需扫描全堆找引用。这大幅减少根扫描和标记开销,使单次回收耗时更稳定、更易预测。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
混合回收(Mixed GC)平衡新老对象回收节奏
当老年代占用达到阈值(-XX:InitiatingHeapOccupancyPercent,默认 45%),G1 启动 Mixed GC,在回收 Eden/Survivor 的同时,掺入部分垃圾多的老年代 Region。它不是一次性清空老年代,而是按需、分批回收,把压力摊到多次 GC 中,避免出现长时间 Full GC。
不复杂但容易忽略的是:Region 划分本身不直接降低停顿,真正起作用的是 G1 在 Region 粒度上做的 增量决策 和 局部回收 —— 把“大任务”拆成多个小任务,并用数据驱动的方式挑最划算的做。

















