垃圾收集器G1ZGC详解
G1与ZGC垃圾收集器深度解析
一、G1收集器(-XX:+UseG1GC)
核心特性
- 定位:面向服务器场景,支持多核处理器与大内存机器
- 目标:高概率满足GC停顿要求的同时保证高吞吐量
- 堆结构:
将Java堆划分为2048个等大小Region(默认计算方式:堆大小/2048,例:4096M堆 → 2M/Region)
保留分代概念但取消物理隔离,代区由不连续Region组成:- Eden:默认占比年轻代80%
- Survivor:S0与S1各占10%
- Old:长期存活对象
- Humongous:专存>50% Region大小的巨型对象(避免直接进入老年代)
📊 Region动态变化:Region功能可动态切换(如年轻代Region回收后可能转为老年代)
GC过程
- 初始标记(STW):标记GC Roots直接引用对象,速度快
- 并发标记:与用户线程并发执行
- 最终标记(STW):修正并发标记阶段变动
- 筛选回收(STW):
- 按回收价值排序Region
- 根据
-XX:MaxGCPauseMillis
(默认200ms)制定回收计划 - 采用复制算法减少内存碎片
GC分类
GC类型 | 触发条件 | 特点 |
---|---|---|
YoungGC | Eden占满且预计回收时间≈MaxGCPauseMillis | 动态扩展年轻代Region(不超过堆60%,-XX:G1MaxNewSizePercent 调节) |
MixedGC | 老年代占用≥-XX:InitiatingHeapOccupancyPercent (默认45%) | 回收所有Young+部分Old+Humongous,复制算法 |
Full GC | MixedGC时无足够Region承载存活对象 | 单线程STW整理(Shenandoah已优化为多线程) |
调优参数
-XX:+UseG1GC # 启用G1
-XX:MaxGCPauseMillis=200 # 目标停顿时间
-XX:G1HeapRegionSize=2m # 手动指定Region大小
-XX:G1NewSizePercent=5 # 新生代初始占比
-XX:G1MaxNewSizePercent=60 # 新生代最大占比
-XX:InitiatingHeapOccupancyPercent=45 # 触发MixedGC的老年代阈值
优化建议
- 避免过早晋升老年代:合理设置
MaxGCPauseMillis
,平衡年轻代GC频率与存活对象量 - 适用场景:
- 堆内存 > 8GB
- 停顿要求 < 500ms
- 对象分配速率变化大
✅ 高并发实践:Kafka类消息系统(64G堆+
MaxGCPauseMillis=50ms
)可兼顾低停顿与高吞吐
二、ZGC收集器(-XX:+UseZGC)
核心目标
- 支持TB级堆:理论最大16TB(42位地址指针)
- 停顿≤10ms:与堆大小无关
- 吞吐损失<15%:读屏障导致额外开销
- NUMA感知:优先访问本地内存
关键技术
1. 颜色指针(Colored Pointers)
- 64位指针结构:
- 18位:保留
- 1位:Finalizable
- 1位:Remapped
- 1位:Marked1
- 1位:Marked0
- 42位:对象地址
- 优势:
- Region回收后立即重用
- 减少内存屏障使用
- 扩展性强
2. 读屏障(Load Barrier)
Object o = obj.fieldA; // 触发读屏障
if (指针为Bad Color) {修正到新地址; // "自愈"(Self-Healing)
}
内存布局
Region类型 | 容量 | 用途 |
---|---|---|
Small | 2MB | 存储<256KB对象 |
Medium | 32MB | 存储256KB~4MB对象 |
Large | N×2MB | 存储≥4MB大对象(不可重分配) |
运作过程
- 并发标记:遍历对象图更新指针标志位
- 预备重分配:统计需清理的Region组成RelocationSet
- 并发重分配:
- 复制存活对象到新Region
- 维护转发表(Forward Table)
- 并发重映射:合并到下次标记阶段,修正旧引用
参数配置
-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC # 启用ZGC
-XX:ConcGCThreads=4 # 并发GC线程数
-XX:ZAllocationSpikeTolerance=5 # 分配速率敏感度
现存问题
- 浮动垃圾:全堆扫描导致新对象难以及时回收
- 无分代:短命对象回收效率低
- 解决方案:增大堆容量(治标),未来引入分代(治本)
三、收集器选型指南
选择策略
- 堆<100M:串行收集器
- 单核无停顿要求:串行/JVM自动选择
- 停顿容忍>1s:并行
- 响应时间<1s:并发收集器(G1/ZGC)
- 推荐场景:
- 4G~8G:ParNew+CMS
- 8G+:G1
- 百G+:ZGC(JDK11+)
版本演进
- JDK8默认:Parallel(年轻代+老年代)
- JDK9+默认:G1
附:安全点与安全区域
安全点(Safe Point)
- 位置:方法返回前/调用方法后/异常抛出点/循环末尾
- 机制:轮询中断标志,主动挂起
安全区域(Safe Region)
- 作用:保障Sleep或阻塞线程在GC时的安全性
- 范围:引用关系稳定的代码片段