垃圾回收机制

垃圾回收机制

目的:清除不再使用的对象,腾出占用的内存空间

比如,当给一个变量重新赋值了一个新对象后,原来的对象就不再使用了

策略

引用计数法

  • 当一个对象被引用时-引用次数 +1
  • 当一个对象被取消引用时-引用次数 -1
  • 引用数为 0 时-触发垃圾回收机制回收

缺陷:循环引用时-引用次数永远不可能为 0 ,无法回收,内存无法释放

循环引用: 当对象 OA 的属性 A 引用了 OA 对象本身,把变量重新赋值后,原来的 A 对象还是指向原来的 OA 内存空间,从而导致无法回收

标记清除法

关键点-标记、清除

  • 首先将所有对象标记为 0 ,从根对象开始遍历,将存活的对象标记为 1
  • 将标记为 0 的对象清除掉
  • 最后将所有标记为 1 的对象重新标记为 0 ,方便下一次垃圾回收机制回收

问题: 对象内存空间位置是不连续的,如果进来一个新对象,找位置是个新问题

内存空间找位置

有三种方法分别是 First-fit、Best-fit、Worst-fit

  • First-fit: 找到能放置下新对象的第一个块位置
  • Best-fit: 找到能放置下新对象的最小的块
  • Worst-fit: 找到最大的块,分一块空间给新对象

First-fit 性能最好
Worst-fit 会产生更多不连续的空间

V8 对垃圾回收机制的优化

优化标记算法

有些对象需要频繁回收,有些对象不需要频繁的回收

  • 一般小的、新的、存活时间短的对象,需要频繁回收
  • 大的、老的、存活时间长的对象不需要频繁回收

所以在内存堆中分出了两个区域,分别是新生代区域、老生代区域

  • 新生代区域-小、新、存活时间段
  • 老生代区域-大、老、存活时间长

新生代区域

内部有俩个空间,分别是 from 空间、to 空间

  • from-使用空间
  • to-闲置空间
  1. 当 from 空间要满的时候,开始标记,将存活的对象标记好
  2. 标记好后将他们复制到 to 空间中
  3. 最后再吧 from 空间清空,并且交换空间名称 to->from from->to

老生代区域

  1. 首先将所有对象标记为 0
  2. 将存活的对象标记为 1
  3. 将标记为 0 的对象全部清除
  4. 将标记为 1 的对象全部标记为 0
  5. 通过标记压缩算法整理内存空间位置

其他

执行机制

由于JS是单线程语言-执行垃圾回收机制时,JS 执行会被暂停(全停顿),V8 对这种情况做了一定的优化—垃圾回收机制支持多线程,并行回收

但依然可能出现阻塞 JS 执行的情况

于是就有了 增量标记

增量标记

特点:垃圾回收可以分段执行-JS和垃圾回收分段轮流交叉执行,最大化保证 JS 的执行

通过三色标记法来记录上一次执行的位置

三色标记法

作用: 将上次标记到的位置标记为灰色,当下次执行时从灰色标记位置开始重新标记

并发回收

JS 在主线程执行,垃圾回收在辅助线程执行


垃圾回收机制
http://blog.climbed.online/2023/11/24/Web -- Knowledge is infinite/前端/JavaScript/垃圾回收机制/
作者
Z.K.
发布于
2023年11月24日
许可协议