标记-清除算法执行路径为“先标再清”,先暂停程序递归标记存活对象,再线性扫描回收未标记内存,不移动对象导致碎片化且全堆扫描开销大。

标记-清除算法的执行路径很直接,核心就是“先标再清”,不依赖对象年龄或内存分区,适合实现轻量级回收器。
标记阶段:从根出发,递归标记所有存活对象
这个阶段必须暂停程序(Stop-the-World),确保对象引用关系稳定。 它从 GC Roots 开始遍历——包括栈上局部变量、全局变量、寄存器中指针、已注册的静态根对象等。 标记过程是深度优先或广度优先的可达性分析: - 扫描栈内存范围(通过 `__builtin_frame_address(0)` 获取栈顶,结合预设栈底地址确定边界) - 遍历堆中已分配对象,对每个对象内嵌的指针字段做递归标记 - 使用位图或对象头中的标记位记录状态,避免重复访问清除阶段:线性扫描堆,回收未标记内存
标记完成后,GC 线性遍历整个堆内存块: - 对每个对象检查标记位,未标记即视为垃圾 - 直接释放其占用内存,加入空闲链表或重置为可用状态 - 若对象注册了析构函数(如 `gc_malloc` 的回调),在此阶段调用 - 不移动存活对象,也不整理内存布局执行路径的典型约束与副作用
该路径天然带来三个关键影响: - 每次 GC 都需全堆扫描,时间开销与堆大小正相关 - 存活对象位置不变,导致空闲内存碎片化,后续大对象分配可能失败 - 标记过程修改对象头或位图,可能触发写时复制(Copy-on-Write)机制,增加页表开销实际运行中的关键控制点
开发者能干预的环节有限但重要: - 合理设置栈底地址(`bos`),避免漏扫栈上临时指针 - 主动注册长期存活对象为静态根(`gc_malloc_static`),防止误回收 - 控制 `gc_stop` 调用时机,决定是否立即释放全部堆内存而非增量回收不复杂但容易忽略











