通过阅读 C++ 源码中 TimingLogger::ScopedTiming 的打点位置,我们可以把收集到的时间数据严格映射到 CC 算法的生命周期中。核心执行流程由 ConcurrentCopying::RunPhases() 函数统领。
源码中大量使用了 TimingLogger::ScopedTiming split("PhaseName", GetTimings());。这是 ART 内部的一个树状计时器。当你看到 Total(代码里直接叫 split 的名字)时,它代表整个块的运行时间;而 Exclusive 就是 ART 的打点系统在输出日志时,自动用 Total 减去它内部嵌套的所有子 split 耗时后计算出来的。
1. 准备阶段 (Concurrent)
这是 GC 刚启动时的初始化工作,此时应用线程仍在正常运行。
InitializePhase_Total_s: 整个初始化阶段的总耗时。在这里 GC 会重置内部状态,判断本次 GC 是否需要强制全量疏散 (force_evacuate_all_),并绑定各类内存空间的 Bitmap。MarkZygoteLargeObjects_s: 位于InitializePhase内部。GC 会遍历大对象空间 (Large Object Space),显式标记那些属于 Zygote 的大对象,以防止它们被意外回收。
2. 并发标记阶段 (Concurrent)
如果是全量 GC (Full GC) 而不是分代年轻代 GC,就会执行此阶段。
MarkingPhase_Total_s: 标记阶段总耗时。ScanImmuneSpaces_s: 扫描“免疫空间”(如 Image Space 和 Zygote Space),这些空间的对象通常不需要被回收,但需要扫描它们指向其他空间的引用。VisitConcurrentRoots_s&VisitNonThreadRoots_s: 扫描虚拟机运行时的全局根节点(非线程特定的根)。CaptureThreadRootsForMarking_s: 触发一个 Checkpoint,让所有应用线程短暂挂起,将其局部的根节点引用捕获到标记栈中。
3. 翻转与 STW 阶段 (Stop-The-World)
真正的全局卡顿 (STW) 发生在这个阶段。
FlipThreadRoots_Total_s: 整个线程根节点翻转的生命周期总时间。(Paused)FlipCallback_Total_s: 核心的 STW 操作阶段。源码中明确写有Locks::mutator_lock_->AssertExclusiveHeld(self);,意味着此时 GC 线程独占了全局锁,所有应用线程被强行暂停。(Paused)SetFromSpace_s: 将当前被占用的区域标记为From-Space,为后续的拷贝腾出逻辑空间。(Paused)GrayAllNewlyDirtyImmuneObjects_Total_s: 极速扫描在 STW 前夕刚刚被应用线程“弄脏”的免疫对象,防止并发执行时发生漏标。(Paused)ClearCards_s: 在扫描完脏卡片后,将其清理。
4. 并发拷贝与处理阶段 (Concurrent)
STW 结束,应用线程恢复运行,GC 线程在后台默默搬运对象。
CopyingPhase_Total_s: 并发拷贝阶段总耗时。ScanCardsForSpace_s: 扫描之前标记的老年代或未疏散区域中的脏卡片,追踪跨代/跨区引用。Process_mark_stacks_and_References_Total_s: 处理标记栈并处理各种引用(软引用、弱引用等)。ProcessReferences_Total_s: 处理弱引用,此阶段会短暂禁用弱引用访问。SweepSystemWeaks_s: 清理系统级别的弱引用(如 JNI WeakGlobalRefs)。
5. 内存回收阶段 (Concurrent)
对象搬运完毕,开始真正释放不再使用的内存。
ReclaimPhase_Total_s: 回收阶段总耗时。Sweep_Total_s/SweepAllocSpace_s/SweepLargeObjects_s: 遍历并清理那些没有被拷贝到To-Space的死对象所占用的内存,包括普通分配空间和大对象空间。RecordFree_Total_s: 记录释放的内存量,计算回收比例。此时region_space_->ClearFromSpace会被调用。ClearFromSpace_s: 物理上清空From-Space区域的数据。Release_free_regions_s: 如果系统内存紧张,会在此刻通过madvise系统调用,急切地将空闲物理内存归还给 Linux 内核。
6. 收尾阶段 (Concurrent)
EmptyRBMarkBitStack_s: 位于FinishPhase中,用于清空 Baker 读屏障所使用的标记位栈,重置状态以备下一次 GC 使用。