新生代GC Minor Collection

141 阅读5分钟

新生代GC Minor Collection

在 JDK 21 的分代式 ZGC(Generational ZGC)中,Minor Collection 是专为高效回收年轻代(Young Generation)对象设计的垃圾回收过程。其核心目标是通过极低延迟(通常 <1ms)快速回收短期存活对象,避免影响应用线程,同时大幅降低 Allocation Stall(内存分配阻塞)风险。以下是其工作原理、技术实现及优化细节的全面解析:


🔄 一、Minor Collection 触发条件

  1. 年轻代空间不足: 当对象分配速率超过回收能力,年轻代 Region 耗尽时触发。
  2. 自适应预测机制: ZGC 实时监控分配速率,通过正态分布预测内存耗尽时间点,提前触发回收(避免被动阻塞)。
  3. 周期性触发: 若启用 XX:ZCollectionInterval 参数,则按固定时间间隔强制执行,应对突发流量。

⚙️ 二、工作流程:并发标记与移动

Minor Collection 全程与用户线程并发执行,仅需极短同步停顿(两次 <1ms 的 STW)。流程分阶段如下:

阶段 1:Pause Mark Start(同步停顿)

  • 目的:初始化标记,创建根集合(GC Roots)。
  • 操作
    • 暂停所有应用线程(STW)。
    • 扫描栈帧、静态变量等 GC Roots,标记直接可达的年轻代对象。
  • 耗时:通常 ≤200μs(与堆大小无关)。

阶段 2:Concurrent Mark/Remap(并发标记与重映射)

  • 目的:标记存活对象,并更新跨代引用。
  • 操作
    • 并发标记:从 GC Roots 遍历对象图,标记所有存活对象(使用染色指针记录状态)。
    • 维护 Remembered Set
      • Store Barrier 实时记录老年代指向年轻代的引用(跨代引用),避免全堆扫描。
      • 通过卡表(Card Table) 标记存在跨代引用的内存页,Minor GC 仅需扫描这些页。
    • 重映射:若对象已被移动(如上次 Major GC),Load Barrier 自动修正引用至新地址。主要是修复上一次gc之后,没有通过读屏障更新引用的引用。
  • 特点:完全并发,无应用线程阻塞。

阶段 3:Pause Mark End(同步停顿)

  • 目的:确认标记结果,准备对象移动。
  • 操作
    • 短暂 STW,校验存活对象集合。
    • 筛选待回收的 Region(死亡对象占比高的区域)。
  • 耗时≤200μs

阶段 4:Concurrent Relocate(并发移动)

  • 目的:将存活对象复制到新 Region,释放连续内存。
  • 操作
    • 复制存活对象
      • 小型Region,死亡对象占比高的region存活对象复制至空闲年轻代 Region(或晋升至老年代)。
      • 小型Region,死亡对象占比低的region不移动存活对象,只标记死亡对象的空间(将死亡对象空间加入空闲链表)
      • 中型Region,与小型Region策略一致
      • 大型Region,将region标记为清除,放回大型region的空闲链表
      • 使用转发表(Forwarding Table) 记录新旧地址映射。
    • 引用更新
      • Load Barrier 拦截对象访问,自动重定向至新地址(零复制感知)。
  • 特点:移动过程并发,应用线程通过屏障无感切换对象地址。

🧩 三、核心技术:屏障与染色指针

分代 ZGC 通过以下技术实现并发回收与低延迟:

技术作用优化效果
染色指针指针高 4 位存储对象状态(如存活、重定位标记)。免去访问对象头,减少内存开销。
Load Barrier读引用时移除元数据位,并修正过期指针(如对象移动后)。实现对象移动的透明化,避免 STW。
Store Barrier写引用时记录跨代指针到 Remembered Set,并标记对象存活。解决跨代引用问题,避免扫描全堆。
Remembered Set存储老年代→年轻代的跨代引用,通过卡表实现位图标记。Minor GC 仅扫描相关内存页,效率提升 10 倍+。

案例:京东压测显示,分代 ZGC 的 Remembered Set 使 Minor GC 耗时降低 85%,吞吐量提升 4 倍。


四、性能优势与调优建议

1. 性能优势

  • 低延迟:全程并发,STW 总时长 <1ms(TB 堆下仍稳定)。
  • 高吞吐:针对性回收年轻代(90% 对象短期消亡),减少无效扫描。
  • 无碎片:复制算法整理内存,避免老年代碎片导致的 Full GC。

2. 调优建议

  • 启用分代模式:JDK 21 需显式开启:

    -XX:+UseZGC -XX:+ZGenerational
    
  • 关键参数

    • Xmx唯一需手动设置的参数,建议为物理内存 60%~80%。
    • XX:ZAllocationSpikeTolerance=2:降低值可提前触发 GC,避免阻塞(默认 2,敏感场景可设 1.5)。
    • Xlog:gc*:启用详细日志,监控 Allocation Stall 频率。
  • 避坑指南

    • 禁用传统参数(如 XmnXX:ConcGCThreads),分代 ZGC 自适应优化更高效。
    • 升级配套组件:Spring Boot ≥2.7.18、Lombok ≥1.18.30。

💎 总结

Minor Collection 是分代 ZGC 的核心创新,通过并发标记、Remembered Set 精准管理跨代引用、读写屏障实现对象移动无感化,在亚毫秒级停顿下高效回收年轻代。其设计本质是以空间换确定性:通过额外内存维护元数据(如卡表、染色指针),换取极低延迟与高吞吐。生产实践表明,分代 ZGC 的 Minor Collection 可降低 Allocation Stall 达 85%,适用于电商秒杀、实时交易等内存敏感型场景。