G1并发标记周期是实现低停顿、高吞吐的关键,包含初始标记、根分区扫描、并发标记、存活数据计算、重新标记和清除六个子阶段,全程以短暂停顿与并发执行结合,依托写屏障和RSet保障准确性,并为混合回收提供带收益评估的Region清单。

G1的并发标记周期是它实现低停顿、高吞吐的关键阶段,核心目标是在应用线程持续运行的同时,准确识别老年代中哪些对象还存活,为后续混合回收(Mixed GC)提供依据。它不追求一次全量扫描,而是分步、渐进、与用户线程并发执行,整体STW时间极短。
并发标记周期包含六个关键子阶段
初始标记(Initial Mark):紧随一次Young GC之后发生,属于STW阶段,但非常短暂。此时只扫描GC Roots直接可达的对象(如Java栈中的局部变量、静态字段等),并标记它们所在Region为“活跃”。这一步快是因为只处理根节点,不遍历对象图。
根分区扫描(Root Region Scanning):在初始标记后立即开始,由并发线程执行,不STW。主要扫描Survivor区中可能持有老年代对象引用的Region(即“根分区”),把跨代引用记录到Remembered Set(RSet)中,确保后续并发标记能覆盖所有可达路径。
并发标记(Concurrent Marking):真正耗时最长的阶段,完全并发运行。从初始标记的存活对象出发,沿引用链逐层遍历,用三色标记法(白→灰→黑)标记所有可达对象。过程中应用线程可自由修改引用,G1通过写屏障(Write Barrier)实时捕获变动,防止漏标。
存活数据计算(Live Data Accounting):标记结束后,并发统计每个Region中存活对象的大小。这个信息用于构建“回收价值模型”,决定后续Mixed GC优先清理哪些Region——垃圾最多、回收收益最大的Region排在前面。
重新标记(Remark):一次短暂停顿(STW),用于处理并发标记期间因应用线程修改引用而产生的“浮动垃圾”或遗漏标记。它会扫描被写屏障记录的脏卡(Dirty Card)、RSet更新、以及未完成的灰色对象,确保标记结果精确。
清除(Cleanup):紧接着Remark的另一次极短STW。主要做两件事:一是释放完全空闲的Region;二是根据存活数据,为下一阶段Mixed GC筛选出候选的老年代Region,并更新Region的分代角色(比如某些Survivor区晋升为Old区)。
为什么这个周期重要
它把原本需要长时间STW的全局标记拆解成多个小任务,大部分交由后台线程异步完成。标记结果不是静态快照,而是动态维护的——靠写屏障和RSet保障准确性。最终输出的不只是“哪些对象存活”,更是一份带成本与收益评估的Region清单,让G1能真正按需、可控地回收,而不是被动等待内存耗尽。
整个周期完成后,G1就进入混合收集阶段,开始有选择地清理年轻代+部分老年代Region,从而兼顾响应性与资源效率。

















