引用计数算法
核心思想:
- 通过维护一个引用数值来回收垃圾对象
优点:
- 发现垃圾时立即回收
- 最大限度减少程序暂停
缺点:
- 无法回收循环引用的对象
- 时间开销大
- 资源消耗大
循环引用示例:
function fn() {
const obj1 = {}
const obj2 = {}
obj1.name = obj2
obj2.name = obj1
return 'lg is a coder'
}
fn()
当fn函数执行完成之后,正常来说obj1和obj2应该被回收,但是这里因为obj2被obj1.name引用,obj1被obj2.name引用,所以造成了无法回收的问题。
标记清除算法
核心思想:分标记和清除两个阶段完成
- 第一阶段: 遍历所有可达对象并标记
- 第二阶段:遍历所有对象清除没有标记的对象,同时清除之前所做的标记,并把回收的空间放到空闲链表上
优点:
- 解决引用计数算法无法解决的循环引用的回收操作
缺点:
- 产生空间碎片化,产生浪费。由于当前所回收的空间在地址上的不连续造成的
- 不会立即回收垃圾对象
图中所示,两边的空间是回收得到的空间,被中间正在使用的空间隔开,如果后续需要申请的内存空间大小刚好为两边空间之和,那就没办法直接使用这两边的空间。
标记整理算法
核心思想:
- 标记整理可以看做是标记清除的增强
- 标记阶段的操作和标记清除一致
- 清除阶段会先执行整理,移动活动对象位置
移动活动对象的位置,然后将非活动对象进行回收。
优点:
- 减少空间碎片化
缺点:
- 不会立即回收垃圾对象