V8 引擎的垃圾回收机制是怎样的?

V8 垃圾回收策略

V8 采用分代回收机制,将堆内存分为新生代和老生代。

新生代(Scavenge 算法)

回收过程:

  1. 从 GC Root 遍历,标记 From 空间中存活的对象
  2. 将存活对象复制到 To 空间
  3. 清空 From 空间
  4. From 和 To 角色互换

特点:空间换时间,适合存活率低的场景

老生代(Mark-Sweep + Mark-Compact)

Mark-Sweep(标记清除):

  1. 标记阶段:从 GC Root 遍历,标记所有可达对象
  2. 清除阶段:清除未标记的对象

问题:产生内存碎片

Mark-Compact(标记整理):

  1. 标记存活对象
  2. 将存活对象向一端移动,紧凑排列
  3. 清除边界以外的内存

特点:解决碎片问题,但移动对象有开销

增量标记与并发回收

引用计数(已弃用)

V8 早期尝试过引用计数,但有循环引用问题:

let a = {}
let b = {}
a.ref = b
b.ref = a
// 引用计数永远不为 0,无法回收

现代 V8 使用可达性分析,彻底解决此问题。

常见内存泄漏场景

  1. 意外的全局变量:function foo() { bar = 1 }(未用 let/var)
  2. 被遗忘的定时器:setInterval 未清除
  3. 闭包引用:不必要的大对象被闭包持有
  4. DOM 引用:元素被移除但 JS 变量仍引用

调试工具

同分类其他题目