1. 垃圾收集器背景与核心挑战在Java虚拟机JVM的内存管理体系中垃圾收集器Garbage Collector承担着自动内存回收的重任。现代JVM主要提供四种垃圾收集器Serial、Parallel、CMS和G1。其中CMSConcurrent Mark-Sweep和G1Garbage-First因其独特的并发特性在大内存应用中广受青睐。CMS收集器采用标记-清除算法通过并发标记阶段减少停顿时间适合追求低延迟的应用场景。但它存在内存碎片问题且无法处理浮动垃圾。G1则采用分区域Region收集策略通过可预测的停顿时间模型兼顾吞吐量和延迟要求。关键区别CMS是传统分代收集器的改良版而G1是面向服务端应用的区域性收集器两者设计哲学存在本质差异。2. CMS收集器工作流程拆解2.1 初始标记阶段Initial Mark这是整个CMS周期中第一个需要暂停应用线程STW的阶段。它仅标记GC Roots能直接关联到的对象速度极快。在HotSpot实现中这个阶段通常借助OopMap数据结构快速定位根引用。// 示例OopMap中的引用记录格式 0x00007f3e6c00f890: 0x000000076b9ff8a0 [oop(0x000000076b9ff8a0)] 0x00007f3e6c00f898: 0x000000076ba02c50 [oop(0x000000076ba02c50)]2.2 并发标记阶段Concurrent Mark在此阶段GC线程与用户线程并发执行。收集器会遍历整个老年代对象图标记所有存活对象。由于用户线程同时运行可能出现以下情况新创建的对象被误标为存活浮动垃圾对象引用关系变化导致漏标需后续重新标记处理2.3 重新标记阶段Remark第二个STW阶段处理并发标记期间遗漏的对象。HotSpot采用增量更新Incremental Update算法通过写屏障记录引用变化。典型耗时在10-100ms之间具体取决于堆大小和对象数量。2.4 并发清除阶段Concurrent Sweep回收未被标记的对象空间。此阶段同样与用户线程并发执行不会导致应用停顿。但会产生内存碎片可能触发Full GC进行压缩。3. G1收集器核心机制解析3.1 区域化内存布局G1将堆划分为多个大小相等的Region默认约2048个每个Region可以是Eden、Survivor或Old类型。这种设计带来两个优势优先收集垃圾比例高的RegionGarbage-First原则避免全堆回收通过多次部分回收达到全局平衡# 查看G1区域信息的JVM参数 -XX:PrintGCDetails -XX:PrintRegionDistribution3.2 混合收集周期G1的工作流程可分为以下阶段3.2.1 初始标记Initial Mark与CMS类似但G1会借助Young GC的STW阶段完成减少额外停顿。该阶段会记录下SATBSnapshot-At-The-Beginning快照。3.2.2 根区域扫描Root Region Scanning扫描Survivor区对老年代的引用确保并发标记的正确性。必须在下次Young GC前完成。3.2.3 并发标记Concurrent Mark与CMS的主要差异使用SATB算法处理引用变化会计算各Region存活对象比例识别完全空闲的Region立即回收3.2.4 最终标记Final Remark处理剩余SATB缓冲区引用执行引用处理如类卸载。此阶段也是STW的。3.2.5 清理阶段Cleanup统计各Region存活对象排序回收优先级。部分Region会在此阶段被回收。4. 关键流程对比与可视化4.1 CMS工作流程图[STW] Initial Mark → [Concurrent] Marking → [STW] Remark → [Concurrent] Sweeping4.2 G1工作流程图[STW] Initial Mark (with Young GC) ↓ [Concurrent] Root Region Scanning ↓ [Concurrent] Marking ↓ [STW] Final Remark ↓ [STW] Cleanup4.3 性能特征对比表特性CMSG1算法标记-清除标记-整理停顿目标低延迟可预测延迟内存占用较低较高约10-20%额外适用堆大小8GB4GBFull GC触发条件并发模式失败/晋升失败疏散失败/内存不足5. 调优实践与避坑指南5.1 CMS常见问题并发模式失败当老年代空间不足以容纳晋升对象时触发Full GC。解决方案增加-XX:CMSInitiatingOccupancyFraction值默认68%配合-XX:UseCMSInitiatingOccupancyOnly减少-XX:NewRatio增加年轻代比例内存碎片长期运行后老年代出现不连续空间。可通过以下参数缓解-XX:UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction55.2 G1关键配置最大停顿时间设置合理的-XX:MaxGCPauseMillis默认200ms区域大小-XX:G1HeapRegionSize1MB-32MB2的幂次并行线程数-XX:ParallelGCThreads和-XX:ConcGCThreads实测建议G1的-XX:InitiatingHeapOccupancyPercent默认45%需要根据对象分配速率调整过晚启动会导致并发周期来不及完成。6. 生产环境监控要点6.1 CMS监控指标Concurrent mode failure次数最后一次GC持续时间jstat -gcutil老年代碎片率通过GC日志计算6.2 G1监控重点Evacuation Failure发生频率Remembered Set大小jcmd VM.native_memory混合收集效率存活对象/回收区域比# 获取G1详细信息的命令示例 jcmd pid GC.heap_info jstat -gccause pid 1s在大型电商系统中我们曾遇到G1的Humongous对象分配导致频繁Full GC的情况。通过设置-XX:G1HeapRegionSize16MB并配合-XX:G1ReservePercent15成功将99%的GC停顿控制在150ms以内。这印证了G1设计哲学的核心——通过合理的区域划分和回收策略在吞吐量与延迟之间取得最佳平衡。
阅读完成 · 觉得有帮助?