js V8 Engine GC All In One
js 垃圾回收原理
JavaScript 有两种
策略
实现垃圾回收
机制
- 标记清除 ✅
- 引用计数 ❌
标记清除法
标记清除法:当程序执行流入到一个函数中时,会创建该函数的执行上下文
,执行上下文中的变量都会被标记
为进入环境,从逻辑上讲,永远不能释放进入执行环境变量所占用的内存。因为只要执行流进入相应的执行上下文,就可能会用到这些变量。
标记清除的工作流程:
- 垃圾收集器在运行的时候会给存储在内存的中的 所有变量都
加上标记
去掉
执行上下文中的变量 以及 被环境中的变量引用的变量 的标记
- 那些 还存在标记的变量将被视为准备删除的变量
- 最后
垃圾收集器
完成内存清除
工作,销毁
那些带标记的值并回收它们所占用的内存空间
引用计数法
引用计数法, 跟踪记录每个值被引用
的次数
,当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是 1,如果这个值再被赋值给另一个变量,则引用次数加 1
。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减 1
。当这个引用次数变成 0
时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。这样,垃圾收集器
下次再运行时,它就会释放
那些引用次数为 0 的值所占的内存
。
这种垃圾收集方式存在一个比较大的问题就是循环引用
,就是说对象 a 包含一个指向 b 的指针,对象 b 也包含一个指向 a 的引用。 这就可能造成大量内存得不到回收
,也就是内存泄漏
,这是因为它们的引用次数永远不可能是 0。
// circular reference error
function cycleReferenceBug() {
var a = new Object();
var b = new Object();
a.ref = b;
b.ref = a;
}
Memory Management / 内存管理
// 自动 GC
// 手动 GC
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
《JavaScript权威指南(第四版)》
由于字符串、对象和数组没有固定大小
,所有当他们的大小已知时,才能对他们进行动态的存储分配
。
JavaScript程序每次创建
字符串、数组或对象时,解释器
都必须分配内存
来存储那个实体。
只要像这样动态地分配
了内存,最终都要释放
这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。