bigywater.tech
Java · 146

G1 垃圾收集器:Region、记忆集和停顿目标

G1 的 Region、停顿目标和记忆集分别是什么、有多大影响?这篇用 -Xlog:gc 与 gc+phases=debug 的真实日志逐项量出来(晋升规则见上一篇,Humongous 对象与 G1 记忆集的专门篇目在后面)。

1M / 4M / 16M
-Xmx64m(512m、2g) / 8g / 32g 下的 Region 大小
51.7 → 22.2 MB
MaxGCPauseMillis 50 ms → 5 ms 时平均 Eden 大小
0.65 → 5.59 ms
老年代大量指向新对象的引用让年轻代停顿中位数涨到这么多

Region

实测 · 本机执行输出
  -Xmx64m   → Region 大小 1M
  -Xmx512m  → Region 大小 1M
  -Xmx2g    → Region 大小 1M
  -Xmx8g    → Region 大小 4M
  -Xmx32g   → Region 大小 16M

停顿目标

实测 · 本机执行输出
        目标      年轻代 GC 次数        停顿中位数(ms)     最大(ms)     平均 Eden 大小(MB)
      5 ms           1692             1.14       3.39               22.2
     50 ms            711             1.59       9.28               51.7
    200 ms            725             1.54       9.02               52.0

并发标记周期

实测 · 本机执行输出
  整个 6 秒里各类停顿的次数:
    Young                 230 次
    Young(并发标记开始)         241 次
    Remark                241 次
    Cleanup               241 次
    Young(准备 Mixed)       241 次
    Mixed                 243 次
  从一次「并发标记开始」到下一次之间的停顿序列(一个完整周期):
    Young(并发标记开始) → Remark → Young → Cleanup → Young(准备 Mixed) → Mixed → Young×57
  日志里的并发阶段: ['Mark Cycle']

记忆集

实测 · 本机执行输出
  [老年代有大量指向新对象的引用] 年轻代 GC 118 次,停顿中位 5.59 ms;平均每次:Merge Heap Roots 0.09 ms、Scan Heap Roots 2.04 ms、Object Copy 3.02 ms,待处理的脏卡片 23938 张
  [没有这种引用] 年轻代 GC 284 次,停顿中位 0.65 ms;平均每次:Merge Heap Roots 0.03 ms、Scan Heap Roots 0.00 ms、Object Copy 0.00 ms,待处理的脏卡片 11 张

分步演示

G1 内部
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,G1(-XX:+UseG1GC),日志用 -Xlog:gc、gc+heap、gc+phases=debug
    • 没有验证:IHOP 阈值的具体数值与自适应、并发线程数的影响、Full GC 的触发(本篇的负载没有触发)、大堆(几十 GB)下的停顿、JDK 17 与 27 的 G1 差异、并发标记各阶段的耗时;各数字来自一次 4 到 6 秒的运行
    京ICP备2026067502号-1京公网安备11010502063487号