G1 参数设置/Region/记忆集
G1 的关键参数
G1 有丰富的参数可以调优,但大多数情况下默认配置已经足够好。以下是需要重点关注的参数。
Region 相关参数
G1HeapRegionSize
设置 G1 Region 的大小:
bash
# 默认值:自动计算(1MB~32MB,必须是 2 的幂)
# 手动设置:
java -XX:G1HeapRegionSize=4m MyApp
# RegionSize 建议:
# - 堆小(< 4GB):Region 1MB
# - 堆中(4~32GB):Region 2MB 或 4MB
# - 堆大(> 32GB):Region 8MB 或 16MB为什么要设置 RegionSize
| 堆大小 | 默认 RegionSize | 说明 |
|---|---|---|
| < 4GB | 1MB | 适合小堆 |
| 4~32GB | 2MB 或 4MB | 平衡 |
| > 32GB | 8MB 或 16MB | 大堆需要大 Region |
停顿时间参数
MaxGCPauseMillis
G1 最重要的参数:目标最大停顿时间。
bash
# 设置目标停顿时间 200ms
java -XX:MaxGCPauseMillis=200 MyApp
# 设置目标停顿时间 100ms(更激进)
java -XX:MaxGCPauseMillis=100 MyApp注意:MaxGCPauseMillis 是一个软目标,不是硬性保证。JVM 会尽力满足,但不一定能保证。
bash
# MaxGCPauseMillis 的影响:
# 设置值越小 → G1 会收集更少的 Region → 停顿时间短
# 设置值越大 → G1 会收集更多的 Region → 停顿时间长但吞吐更高G1HeapWastePercent
设置允许的 GC 浪费空间比例:
bash
# 默认值:5%
# 表示:如果空闲空间占堆的 5%,G1 可以停止收集
java -XX:G1HeapWastePercent=10 MyApp年轻代参数
NewRatio 和 NewSize
bash
# 设置年轻代比例(老年代:年轻代 = NewRatio:1)
java -XX:NewRatio=2 MyApp
# 例如:堆 4GB,NewRatio=2 → 年轻代约 1.3GB,老年代约 2.7GB
# 或者直接设置年轻代大小
java -Xmn2g -XX:+UseG1GC MyAppSurvivorRatio
bash
# 设置 Survivor 比例(Eden : Survivor)
# 默认值:8:1:1
java -XX:SurvivorRatio=4 MyApp
# Eden : Survivor = 4:1:1InitialNewSize / MaxNewSize
bash
# 设置年轻代初始大小
java -XX:InitialNewSize=512m MyApp
# 设置年轻代最大大小
java -XX:MaxNewSize=2g MyApp混合收集参数
InitiatingHeapOccupancyPercent
设置触发并发标记周期的堆使用率阈值:
bash
# 默认值:45(即老年代使用率达到 45% 时开始并发标记)
java -XX:InitiatingHeapOccupancyPercent=50 MyAppG1MixedGCLiveThresholdPercent
混合收集时,Old Region 中存活对象比例超过这个阈值就不会被回收:
bash
# 默认值:85%
# 即:Old Region 中存活对象超过 85% 时,不值得回收
java -XX:G1MixedGCLiveThresholdPercent=90 MyAppG1MixedGCCountTarget
一次混合收集周期中,最多执行多少次混合 GC:
bash
# 默认值:8
java -XX:G1MixedGCCountTarget=16 MyAppG1 的 Remembered Set
什么是 Remembered Set
每个 G1 Region 都有一个 Remembered Set(RSet),记录「谁引用了我」:
┌────────────────────────────────────┐
│ Old Region │
│ │
│ RSet(记忆集): │
│ ├─ Eden Region A ──→ 引用了 Young Obj │
│ └─ Eden Region B ──→ 引用了 Young Obj │
│ │
└────────────────────────────────────┘RSet 的作用
RSet 是 G1 实现可预测停顿的关键:
| 作用 | 说明 |
|---|---|
| 避免全堆扫描 | GC 时不需要扫描整个堆,只需扫描 RSet |
| 精确回收 | 知道哪些 Region 有跨 Region 引用 |
| 并发优化 | RSet 的更新是并发的 |
RSet 的内存开销
RSet 需要额外的内存,每个 Region 的 RSet 大小取决于引用它的 Region 数量:
bash
# 默认情况下,RSet 占用约 5%~10% 的堆内存
# 可以通过参数调节:
java -XX:G1RSetUpdatingPauseTimePercent=5 MyAppG1 调优实战
场景一:低延迟 Web 服务
bash
# 目标:停顿时间不超过 200ms
java -Xms4g -Xmx4g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:InitiatingHeapOccupancyPercent=45 \
-XX:G1HeapRegionSize=4m \
MyApp场景二:高吞吐批处理
bash
# 目标:最大化吞吐量,允许较长停顿
java -Xms8g -Xmx8g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=500 \
-XX:G1HeapWastePercent=10 \
-XX:G1MixedGCCountTarget=16 \
MyApp场景三:大内存机器
bash
# 64GB 堆,Region 大一些减少 RSet 开销
java -Xms64g -Xmx64g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:G1HeapRegionSize=8m \
-XX:InitiatingHeapOccupancyPercent=50 \
MyApp常见问题与解决
| 问题 | 原因 | 解决 |
|---|---|---|
| 停顿时间过长 | 收集 Region 太多 | 减小 MaxGCPauseMillis |
| Full GC 频繁 | 对象晋升太快 | 增大 Survivor、降低晋升阈值 |
| Humongous 对象多 | 大对象太多 | 增大 RegionSize 或调整阈值 |
| GC 时间占比高 | 吞吐量不够 | 增大堆、减小 MaxGCPauseMillis |
本节小结
G1 核心参数速查:
| 参数 | 作用 | 默认值 |
|---|---|---|
-XX:MaxGCPauseMillis | 目标最大停顿时间 | 200ms |
-XX:G1HeapRegionSize | Region 大小 | 自动(1~32MB) |
-XX:InitiatingHeapOccupancyPercent | 触发并发标记的堆使用率 | 45% |
-XX:G1HeapWastePercent | 允许的浪费空间 | 5% |
-XX:G1MixedGCLiveThresholdPercent | Old Region 回收阈值 | 85% |
-XX:NewRatio | 年轻代比例 | 动态 |
理解 G1 的参数,是进行精细调优的基础。
下一节,我们来看 G1 回收过程/优化建议。
