识别并发标记阶段需定位起始、进行中和结束信号:G1用[GC concurrent-mark-start]和[GC concurrent-mark-end];CMS为[CMS-concurrent-mark-start]及[CMS-concurrent-mark]耗时行;ZGC在Pause Mark Start后进入Concurrent Mark,以Concurrent Mark Cycle Complete标志完成;Shenandoah则通过Concurrent marking或Concurrent evacuation标识。

看Java GC日志中的并发标记阶段,关键不是找“正在标记”的实时过程,而是定位它开始、进行中和结束的明确信号——因为并发标记本身不暂停应用,日志里没有连续流式记录,只有几个标志性事件。
识别并发标记起始点
所有主流收集器都用固定格式标识并发标记启动:
-
G1:查
[GC concurrent-mark-start],它出现在初始标记(STW)之后,标志真正并发遍历开始 -
CMS:日志中紧接
[CMS-initial-mark]后出现[CMS-concurrent-mark-start] -
ZGC:对应
Pause Mark Start暂停结束后,日志会进入Concurrent Mark阶段(无单独start行,但时间戳连续、无pause标签) -
Shenandoah:查找
Concurrent marking或Concurrent mark开头的行
确认并发标记正在进行
这个阶段的日志条目通常带耗时统计,且明确标注“concurrent”:
- G1 中常见:
[GC concurrent-mark: 2.145/2.150 secs]——斜杠前是CPU时间,后是实际耗时,差值反映线程等待或I/O开销 - CMS 中:
[CMS-concurrent-mark: 1.892/1.901 secs],后面还可能跟[CMS-concurrent-preclean-start] - ZGC 不打印中间进度,但
Concurrent Mark阶段持续期间,日志中不会出现新的gc,pause,只有gc,mark类标签
定位并发标记完成节点
完成不等于回收完成,而是为后续STW阶段做准备:
立即学习“Java免费学习笔记(深入)”;
-
G1:查
[GC concurrent-mark-end],之后大概率紧跟[GC remark](最终标记,STW) -
CMS:
[CMS-concurrent-mark]行末尾即为完成;紧接着是预清理和可中止预清理,最后是[CMS-remark] -
ZGC:日志中出现
Concurrent Mark Cycle Complete,表示本轮标记闭环结束,随后触发Pause Relocate Start -
Shenandoah:查
Concurrent evacuation或Concurrent cleanup的起始,说明标记已就绪并进入执行阶段
辅助判断是否异常拖长
并发标记耗时过长往往暴露堆结构问题,可交叉观察这些线索:
- 频繁出现
[GC concurrent-cleanup-start]或大量[GC ref-proc],说明引用更新压力大,RSet维护成本高 - 日志中夹杂
Humongous allocation或Humongous regions reclaimed,提示巨型对象干扰了并发节奏 - 同一轮标记中
concurrent-mark耗时远超以往(比如从1秒涨到8秒),且remark时间也同步拉长,大概率是老年代对象图深度或跨代引用暴增


















