
1. G1垃圾回收器现代Java应用的性能救星第一次接触G1Garbage-First是在2017年处理一个电商大促预案时当时我们的CMS回收器在堆内存超过6GB后频繁出现并发模式失败。切换到G1后不仅解决了问题还将GC停顿时间控制在200ms以内。作为JDK 9及以后版本的默认垃圾回收器G1通过创新的Region内存布局和可预测的停顿时间模型彻底改变了传统垃圾回收器的工作方式。G1的核心设计目标很明确在大内存4GB以上场景下以可控的停顿时间通常100-500ms实现高吞吐量。与Parallel Old的全堆压缩和CMS的老年代标记清除不同G1将堆划分为2048个左右的等大小Region默认约2MB每个Region可以是Eden、Survivor或Old区。这种设计带来三个革命性优势并行与并发结合的回收策略年轻代回收Young GC完全并行而混合回收Mixed GC可以并发执行增量式压缩通过每次回收部分Region来避免全堆压缩导致的长时间停顿停顿时间预测基于Region回收成本的历史数据精确控制每次GC的耗时关键提示G1的Region大小通过-XX:G1HeapRegionSize指定建议保持默认值堆大小/2048过小的Region会导致记忆集膨胀过大会降低停顿时间精度2. Region划分内存管理的乐高积木2.1 Region的动态角色分配在传统的分代垃圾回收器中内存空间被静态划分为固定的年轻代和老年代。而G1的每个Region都可以在运行时动态改变身份// 通过HotSpot源码看Region类型定义摘自g1HeapRegion.hpp enum RegionType { Free, // 未分配区域 Eden, // 年轻代Eden区 Survivor, // 年轻代Survivor区 Old, // 老年代 Humongous, // 巨型对象区 Archive, // 存档区域CDS特性 G1EdenSurvivor // 过渡状态 };当应用申请内存时G1会优先从Free Region分配。对于普通对象小于Region一半大小会被分配到Eden Region超过Region 50%的大对象则进入Humongous Region可能连续占用多个Region。这种设计带来两个显著优势内存利用率提升不再有年轻代/老年代的固定比例限制-XX:NewRatio失效完全根据GC效率动态调整巨型对象处理优化连续分配的Humongous Region避免了传统回收器中大对象导致的提前晋升问题2.2 跨代引用与记忆集Remembered Set每个Region都附带一个记忆集Remembered Set用于记录其他Region对该Region内对象的引用。这种设计解决了跨代引用的扫描难题Region A (Old) - 对象X Region B (Eden) - 引用对象X在年轻代回收时传统回收器需要扫描整个老年代找跨代引用而G1只需检查Eden Region对应的记忆集。记忆集实现采用卡表Card Table的变体每个Region被划分为512字节的卡页Card写屏障Write Barrier在对象引用更新时标记脏卡并行线程定期扫描脏卡更新记忆集避坑指南记忆集可能占用堆大小的10-20%对于超大堆建议调整-XX:G1RSetUpdatingPauseTimePercent默认10%控制更新耗时3. 混合回收G1的核心回收策略3.1 回收阶段全景图G1的回收过程分为三个主要阶段形成完整的闭环年轻代回收Young GC触发条件Eden区耗尽过程完全STW的并行标记-复制存活对象转移到Survivor或Old Region特点只处理年轻代Region依赖记忆集避免全堆扫描并发标记周期Concurrent Cycle触发条件堆占用超过IHOP阈值-XX:InitiatingHeapOccupancyPercent默认45%过程初始标记Initial MarkSTW与Young GC同步进行根区域扫描Root Region Scan并发扫描Survivor Region并发标记Concurrent Mark与应用线程并行最终标记RemarkSTW处理SATBSnapshot-At-The-Beginning队列清理CleanupSTW统计存活对象最多的Region混合回收Mixed GC触发条件并发标记周期完成后特点同时回收年轻代和有价值的老年代Region根据回收效益排序目标逐步将堆占用降到-XX:G1HeapWastePercent默认5%以下3.2 停顿时间预测机制G1通过历史数据预测每次回收的耗时核心参数是-XX:MaxGCPauseMillis默认200ms目标最大停顿时间-XX:GCPauseIntervalMillis可选期望的GC间隔预测算法主要考虑Region存活对象比例通过并发标记获得复制单个Region的历史耗时记忆集处理成本实际工作中我通过以下JVM参数优化预测精度-XX:G1ReservePercent10 # 保留内存应对晋升失败 -XX:G1ConcRefinementThreads4 # 并发记忆集更新线程4. 实战调优从理论到落地4.1 关键参数速查表参数默认值推荐调整作用-XX:MaxGCPauseMillis200ms根据SLA设置目标最大停顿时间-XX:InitiatingHeapOccupancyPercent45%50-60%触发并发标记的堆占用阈值-XX:G1HeapRegionSize自动计算1-32MBRegion大小-XX:G1NewSizePercent5%保持默认年轻代最小占比-XX:G1MaxNewSizePercent60%保持默认年轻代最大占比-XX:ConcGCThreads-CPU核数1/4并发标记线程数-XX:ParallelGCThreads-CPU核数并行回收线程数4.2 典型问题排查指南问题1并发模式失败Concurrent Mode Failure现象GC日志出现Evacuation Failure或To-space exhausted原因混合回收速度跟不上对象分配速率解决方案增加-XX:ConcGCThreads提升并发标记速度降低-XX:InitiatingHeapOccupancyPercent提前触发并发标记增加-XX:G1ReservePercent预留更多内存问题2记忆集占用过高现象堆内存充足但频繁Full GCGC日志显示Remembered Sets占用大原因跨Region引用过多解决方案检查业务代码避免过度使用全局集合调整-XX:G1RSetUpdatingPauseTimePercent限制记忆集更新时间考虑增大Region大小减少Region总数问题3长时间停顿1s现象个别GC事件远超MaxGCPauseMillis原因Humongous对象分配或系统调用干扰解决方案添加-XX:PrintGCDetails分析停顿阶段使用-XX:G1SummarizeRSetStats检查记忆集状态考虑禁用Linux透明大页THP5. 进阶技巧超越默认配置5.1 巨型对象优化策略对于频繁分配大对象如缓存系统的场景建议-XX:G1HeapRegionSize4M # 增大Region减少Humongous对象 -XX:G1EagerReclaimHumongousObjectstrue # 主动回收巨型对象 -XX:G1EagerReclaimHumongousObjectsWithStaleRefstrue # 回收无引用巨型对象5.2 日志分析与可视化推荐GC日志配置-Xlog:gc*debug:filegc.log:time,uptime,level,tags:filecount10,filesize50M使用工具链分析GCViewer可视化停顿时间和吞吐量JClarity Censum专业GC日志分析Grafana Prometheus实时监控GC指标5.3 与ZGC的对比选择特性G1ZGC最大堆100GB4TB停顿时间10-500ms1ms内存开销10-20%15-20%JDK版本711适用场景百毫秒级SLA亚毫秒级SLA在JDK 17环境中对于超大规模堆100GB且要求亚毫秒停顿的应用建议评估ZGC。但G1在成熟度和调优灵活性上仍有优势