Bootstrap

面试之《js的垃圾回收机制》

目前有四种垃圾回收方法

1. 引用计数

  • 每被引用一次,就增加1,取消引用,减1,到0时,自动清除该变量
  • 问题在于,循环引用会导致变量的引用次数无法清零,也就无法删除该变量
  • 例如,a = {a:1} b = {b:2}, a.b = b, b.a = a
  • 此时a被b.a引用了,b又被a.b引用了,但是a和b并没有被其他地方引用,理论上应该清理,实际并没有

2. 标记清除

  • GC有个根节点root
  • 每次触发垃圾回收机制的时候,从root节点开始广度查找,找到所有与root有关联的空间进行标记
  • 然后把没有被标记的空间,清除掉
  • 这个问题在于,清除掉的空间很分散,无法被合理的利用,造成资源浪费

3. 标记整理

  • 由标记清除引申而来,
  • 标记结束后,将标记后的空间向一侧移动,未被标记的空间就被覆盖了,所以会造成整理后的空间引用地址发生了改变,移动完成后,将整理后未使用的空间都清除掉。
  • 缺点就是整理的过程耗时较长

4. 标记复制

  • 标记阶段与之前一样
  • 标记完成后,将标记后的内容直接复制到新的内容,然后得到一个与标记整理之后相同的区域,再将原来的区域整体清除掉。
  • 最后将复制后的区域当做正在使用的区域。
  • 循环往复
  • 缺点在于需要浪费一半的内存

V8使用的是标记复制+标记整理

  • 首先分为新生代和老生代
  • 新生代用来存放体积小,更新频率高的对象
  • 老生代用来存放体积大,不易更新的对象
  • 新生代采用标记复制的方式,所以一般体积只有64M甚至32M,对半分也只会浪费32M或者16M,当对象占用内存超过分区的1/4时,或者已经被复制过2次以上,就会强制移动至老生代。
  • 老生代就比较大,当内存占满时,就会触发标记整理,来清除那些用不到的内存空间。

以上是我的粗浅见解,如有疑问,可以私信或留言!还望大家共同进步!

;