目录
- G1 GC 定义与原理概述
- G1 GC 的运行机制(Region、分代、并发、混合回收)
- 目标与设计哲学
- 关键 JVM 参数详解(用途、默认值、实践建议)
- 生产级最佳实践建议
- 日志分析与可观测性
- 容器(K8s)环境下最佳实践
- CMS 、G1、ZGC 对比
- 文档链接
1. 定义与背景
G1 (Garbage-First) 是 Java 9+ 的默认服务器端垃圾回收器(Java 11、17、21 都默认用 G1),设计目标是:
在大堆内存中获得低且可预测的停顿时间。
-
前身:CMS(并发标记清理,Stop-the-World 压缩不并发,碎片多)
-
G1 解决的问题:
-
碎片管理
-
并发压缩
-
停顿可预测性
-
📖 官方定义:
The Garbage-First (G1) garbage collector is a server-style collector for multiprocessor machines with large memories that meets garbage collection pause-time goals with high probability, while achieving high throughput.
→ OpenJDK G1 GC官方介绍
2. G1 GC 的运行机制
G1 的核心设计理念是分Region管理堆:
-
整个堆被划分为固定大小的 Region(1MB~32MB,默认自动选)
-
每个 Region 可动态标记为:Eden、Survivor、Old、Humongous
📌 年轻代收集
-
和传统分代类似,Eden → Survivor → Old
-
只回收 Eden 和 Survivor
-
Stop-The-World,但多线程并行
📌 并发标记周期
-
并发标记所有存活对象
-
计算每个 Region 的回收价值(Garbage-First)
📌 Mixed GC
-
关键特性:
-
在Young GC后,同时回收部分Old Region
-
并发标记后触发
-
优先“性价比高”的 Region
-
📌 Humongous Objects
-
超过 Region 大小一半的大对象,直接分配到 Humongous Region
-
可能产生碎片
📌 并发压缩
-
老年代也会整理碎片
-
CMS 的缺点在于不能并发压缩,G1 可以
✅ 参考官方图示(Oracle 官方 GC Guide):
📖 G1 GC Overview - Oracle Docs
3. G1 GC 的设计哲学
参数驱动 = 以暂停时间为目标
-
-XX:MaxGCPauseMillis=N-
G1 的核心指导参数
-
告诉GC团队 “尽量把单次停顿时间控制在N ms以下”
-
⚠️ 但不是严格保证
-
G1 会动态调整
-
年轻代大小
-
Mixed GC 步长
-
并发标记启动阈值
-
4. 主要JVM参数详解
🎯 堆大小
-
建议固定
-Xms8g -Xmx8g
避免扩容引起Full GC。
🎯 Region Size
-
自动估算
-XX:G1HeapRegionSize=8m
可以手工指定(1MB ~ 32MB),但通常不用。
🎯 停顿时间目标
-XX:MaxGCPauseMillis=200
-
G1 会努力在200ms内完成回收。
-
默认200ms,可根据业务要求调整:
-
100~500ms常见。
-
🎯 并发标记启动阈值
-XX:InitiatingHeapOccupancyPercent=45
-
触发并发标记的老年代占用比例
-
降低值 → 提前并发标记 → 更稳定
-
适用于老年代膨胀场景
🎯 并行/并发GC线程
-XX:ParallelGCThreads=8 -XX:ConcGCThreads=4
-
ParallelGCThreads → Stop-The-World 阶段并行线程数
-
ConcGCThreads → 并发标记阶段线程数
建议:
-
ParallelGCThreads ≈ CPU核数-2
-
ConcGCThreads ≈ ParallelGCThreads/2
🎯 并行引用处理
-XX:+ParallelRefProcEnabled
-
并行处理软/弱/虚引用
-
大对象回收时能显著减少停顿
🎯 预分配堆页面
-XX:+AlwaysPreTouch
-
启动时预分配所有堆内存页
-
避免运行时Page Fault
-
建议在生产中开启
堆大小自动感知容器限制(容器)
✅ 参数:
-XX:+UseContainerSupport
✅ 说明:
-
Java 10+ / 11+ 默认开启
-
让JVM自动读取cgroups限制
-
没有这个参数,JVM在容器里会当作是「宿主机内存」来估算默认堆 → 可能太大 → OOMKilled
堆大小比例控制(容器)
✅ 重要参数:
-XX:MaxRAMPercentage
-XX:InitialRAMPercentage
✅ 作用:
-
控制在容器内存限制(cgroups limit)的百分比
-
替代传统的 -Xmx、-Xms 硬编码
✅ 示例:
-XX:MaxRAMPercentage=75 -XX:InitialRAMPercentage=75
-
JVM看到容器限制是 2GB → Max Heap ≈ 1.5GB
✅ 官方推荐(Oracle/OpenJDK):
-
默认 MaxRAMPercentage=25(有点保守)
-
实际生产常用:50–75%
✅ 官方参数手册:
📖 Java 17 GC Tuning Guide
📖 G1 GC Tuning Options - Oracle
5. 生产级最佳实践参数推荐
✅ 推荐生产配置
-Xms8g -Xmx8g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 -XX:+AlwaysPreTouch -XX:+ParallelRefProcEnabled -Xlog:gc*:file=/path/to/gc.log:time,uptime,tags
✅ 容器环境(Kubernetes)
-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=75.0 -XX:+AlwaysPreTouch -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError
-
避免 OOMKilled
-
支持 cgroups 限制
📖 官方文档:
✅ Java in Containers - Oracle Guide
6. GC 日志分析与监控
-
建议开启统一日志格式
-Xlog:gc*:file=/path/to/gc.log:time,uptime,tags
-
重点指标:
-
Total GC Time
-
Pause Times
-
Mixed vs Young GC Ratio
-
Humongous Allocations
-
OldGen Usage
-
IHOP 变化
-
-
工具推荐:
-
GCViewer (开源)
-
GCEasy.io
-
Java Flight Recorder (JFR)
-
Grafana + Prometheus JMX Exporter
-
📖 官方日志格式说明:
✅ Java 17 Logging Command-Line Options
7. 容器 / K8s 环境最佳实践
✅ JVM 参数
-XX:+UseContainerSupport -XX:MaxRAMPercentage=75 -XX:InitialRAMPercentage=75
✅ GC 日志
-Xlog:gc*:file=/mnt/logs/gc.log
✅ AlwaysPreTouch
-
避免K8s热迁移或资源伸缩产生 page fault
✅ 建议分配
-
容器限制 ≈ Xmx / 0.75
-
给OS预留内存
8. CMS、G1、ZGC对比
| 特性 | CMS | G1 | ZGC |
|---|---|---|---|
| 堆布局 | 分代(Young/Old) | Region(动态标签) | Region+染色指针(Load barriers) |
| 老年代回收 | 并发标记清理 | 并发标记+并发压缩 | 并发标记+并发重映射 |
| 碎片整理 | Stop-the-world 压缩 | 并发+增量压缩 | 并发、全程无Stop-the-world压缩 |
| 暂停特性 | 低停顿,但 Full GC 影响大 | 可预测暂停时间(默认200ms) | 极低停顿(通常<10ms) |
| 并发标记 | 是 | 是 | 是 |
| 并发整理 | 否(压缩是STW) | 是 | 是 |
| Humongous对象支持 | 普通分代逻辑 | 特殊Region管理,易触发碎片 | 支持超大对象分配 |
| 特性 | CMS | G1 | ZGC |
|---|---|---|---|
| 停顿可预测性 | 差(碎片会恶化) | ✅ 可预测 | ✅✅ 极好 |
| 并发能力 | 并发标记,清理 | 并发标记,增量压缩 | 几乎全并发 |
| 碎片管理 | 差,需Full GC压缩 | ✅ 并发压缩 | ✅✅ 并发重映射 |
| 复杂对象支持 | 普通分配 | Humongous需特别关注 | ✅ 超大对象也能并发回收 |
| 典型Full GC触发 | 老年代碎片严重 | 极少,除非堆完全爆满 | 极少 |
| 生态支持 | Java 8 → 逐步淘汰 | Java 11+默认,企业首选 | Java 11+可选,Java 17/21成熟 |
9. 文档链接
✅ Oracle 官方 G1 GC 总入口 G1 GC in Java 17
✅ 参数和调优选项 G1 Tuning Options
✅ Java GC Tuning Guide(总览) Java SE 17 GC Tuning Guide
✅ Java in Containers(cgroups 支持)Java in Containers
结论
⭐ G1 GC 是 Java 11+ 的生产默认 GC
⭐ 最适合大堆、低停顿、SLA 有要求的微服务
⭐ 调优要围绕暂停时间目标(MaxGCPauseMillis)
⭐ 监控和日志分析是必须步骤
⭐ 容器化要考虑 cgroups 和堆参数

2155

被折叠的 条评论
为什么被折叠?



