js垃圾回收机制(GC)
一、垃圾回收策略
1.引用计数垃圾回收:
这是最初级的垃圾回收算法,此算法把“对象是否不在需要”简化定义为“有没有其他对象引用到它”。如果没有引用指向该对象,那么该对象会被垃圾回收机制回收。限制:无法回收循环引用。
2.标记-清除算法:
标记清除顾名思义是一种分两阶段对对象进行垃圾回收的算法。
第一阶段:标记。从根结点出发遍历对象,对访问过的对象打上标记,表示该对象可达。
第二阶段:清除。对那些没有标记的对象进行回收,这样使得不能利用的空间能够重新被利用。
这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象并进行标记,把在上下文(全局作用域, 脚本作用域)中声明的变量,以及在全局被引用的变量的标记删除掉, 剩下的所有带标记的变量就被视为要删除的变量, 垃圾回收执行时释放它们占用的内存。(从根开始,垃圾回收器将找到所有可以获得的对象和回收所有不能获得的对象。)
这个算法比前一个要好,因为"有零引用的对象"总是不可获得的,但是相反却不一定,参考“循环引用"。
从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对"对象是否不再需要”的简化定义。
限制:1.那些无法从根对象查询到的对象都将被清除,尽管这是一个限制,但实践中我们很少会碰到类似的情况,所以开发者不太会去关心垃圾回收机制。
2.在清除垃圾之后,剩余对象的内存位置是不变的,就会导致空闲内存空间不连续。这样就出现了内存碎片,并且由于剩余空间不是整块,就需要内存分配的问题。(标记-整理算法可以解决)
二、V8中的垃圾回收机制
- V8引擎的垃圾回收采用标记清除法与分代回收法
- 分为新生代和老生代
针对不同对象采用不同算法:
(1)新生代:对象的存活时间较短。新生对象或只经过一次垃圾回收的对象。
(2)老生代:对象存活时间较长。经历过一次或多次垃圾回收的对象。
回收新生代对象
回收新生代对象主要采用复制算法(Scavenge 算法)加标记整理算法。而Scavenge 算法的具体实现,主要采用了Cheney算法。
对象晋升机制
一轮GC还存活的新生代需要晋升。
回收老生代对象
回收老生代对象主要采用标记清除、标记整理、增量标记算法,主要使用标记清除算法,只有在内存分配不足时,采用标记整理算法。
- 首先使用标记清除完成垃圾空间的回收;
- 采用标记整理进行空间优化;
- 采用增量标记进行效率优化;
浙公网安备 33010602011771号