本文主要介绍JavaScript的垃圾收集机制,具有一定的参考价值。感兴趣的朋友可以参考一下,希望能帮到你。
目录
为什么需要垃圾收集(GC)?什么是垃圾收集垃圾收集策略?引用计数标记循环引用引起的问题?解决方案?引用计数算法的优缺点?关键想法?标记清除算法的优缺点?标记排序算法?V8发动机的垃圾收集?新一代对象提升机制?回收旧代对象参考文档:摘要
为什么需要垃圾回收(GC)
和程序员一样,活久了会产生垃圾,程序运行时也会产生垃圾。如果垃圾堆积过多,程序的运行速度就会变慢。
在JavaScript中,字符串、对象、数组等数据的内存是不固定的,只有在实际使用的时候才会动态分配内存。
当这些数据占用的内存不在使用时,需要释放出来重新使用;否则,当可用内存耗尽时,程序将崩溃。
什么是垃圾回收
垃圾收集机制也称为垃圾收集,简称GC。JavaScript中有一个自动垃圾收集机制。通过一些收集算法,找到不再使用的变量或属性,JS引擎以固定的时间间隔周期性地释放其内存空间。在C/C中,程序员需要手动完成垃圾回收。
垃圾产生
当一个对象没有任何变量或属性来引用它时,我们将永远无法操作它。这个对象是垃圾。太多这样的对象会占用大量内存空间,降低程序速度。
例如:
在这里,我首先声明了一个Person变量,它引用了对象{name:'刘江',age: 20},然后我将这个Person变量指向了另一个对象{name:'辛猿',age: 5000}。那么之前引用的对象现在就没用了,永远不能用来操作它。这种对象只是垃圾。
太多这样的垃圾对象会占用很多空间。如果一直不释放它们,会影响系统性能,甚至导致程序崩溃。所以需要垃圾回收来释放这部分内存。
在这个过程中我们不需要也不能做垃圾收集。
我们只需要将未使用的对象设置为null。
垃圾回收策略
JavaScript中主要的内存管理概念是可达性。大概是指可以通过某种方式访问或使用的值,也就是需要保存在内存中,不可访问,不可使用,然后需要通过垃圾收集机制进行收集的值。
垃圾收集过程不是实时的,因为JavaScript是单线程语言。每次执行垃圾收集时,程序的应用逻辑都会暂停。垃圾收集完成后,将执行应用程序逻辑。这种行为称为完全暂停,因此垃圾收集通常在cpu空闲时执行。
如何以某种方式找到所谓的垃圾是垃圾收集的重点,所以下面是常见的算法策略,但这里只提到前两种:
引用计数算法
标记算法
标记排列
亚恢复
引用计数标记
策略思想:
记录每个变量值被使用的次数。
当变量被声明并且引用类型数据被分配给该变量时,该引用类型数据的引用号被标记为1。
如果将该引用类型数据赋给另一个变量,则引用数为1。
如果变量被其他值覆盖,引用数为-1
当这个引用类型数据的引用号变为0时,这个变量将不会被使用或访问,垃圾收集器将销毁引用号为0的引用类型数据,并在执行过程中回收其占用的内存空间。
例如:
让a={
姓名:“刘江”,
年龄:20岁
};//此时,该对象的引用计数标记为1(一个引用)
设b=a;//此时,对象的引用计数标记为2(a,B引用)
a=空;//此时,对象的引用计数标记为1((b引用))
b=空;//此时,对象的引用计数标记为0(无变量引用)
.//等待GC回收该对象
但是这种方法有一个严重的问题——循环引用。
循环引用引发的问题
在一个函数中,对象A的属性指向对象B,对象B的属性指向对象A,函数执行后,对象A和B的计数器不会为0,影响正常的GC。
例如下面的例子:
功能测试()
{
设A=new Object();
设B=new Object();
a .指针=B;
b .指针=A;
}
test();
当对象A和对象B的属性相互引用时,根据引用计数策略,它们的引用计数都是2,但是在执行test()和执行函数后,函数范围内的数据对象A和对象B都要被GC销毁。
如果执行多次,会造成严重的内存泄漏。
解决方法
在函数的末尾,将它指向null。
//切断引用关系
A=空;
B=空;
引用计数算法的优缺点
优点:
当引用计数为零时,发现的垃圾将被立即收集。
尽量减少程序暂停。
缺点:
无法回收循环引用的对象。
空间成本比较大。
标记清除算法
核心思想
它分两个阶段完成:标记和清除。
大概过程:
在运行时,垃圾收集器会标记内存中的所有变量,假设内存中的所有对象都是垃圾,所有对象都标记为0。
然后从每个根对象开始遍历,将不是垃圾的节点改为1。
清理所有标记为0的垃圾,销毁并回收它们占用的内存空间。
最后将内存中的所有对象标记为0,等待下一轮垃圾回收。
标记清除算法优缺点
优点:
实现简单,标记情况无非是打和不打两种情况,可以用二进制(0和1)标记。
可以回收循环引用的对象
是v8发动机使用最多的算法。
缺点:
垃圾清除后,剩余对象的内存位置不变,会导致空闲内存空间不连续。这就导致了内存碎片,需要解决内存分配的问题,因为剩余空间不是一个完整的块。
标记整理算法
标记紧凑算法可以有效地解决这个问题。标记完成后,标记压缩算法会将不需要清理的对象移到内存的一端,最后在边界处清理内存。
V8引擎的垃圾回收
V8发动机的垃圾收集采用标记清除法和生成回收法。
分为新生代和老一代。
针对不同对象采用不同算法:
(1)新生代:物体存活时间短。新对象或只被垃圾回收过一次的对象。
(2)老一代:对象寿命较长。经历了一次或多次垃圾回收的对象。
回收新生代对象
新一代回收对象主要采用复制算法(清除算法)加上标记整理算法。清除算法的具体实现主要采用切尼算法。
对象晋升机制
新一代胃癌幸存者需要提升。
回收老生代对象
老一代对象主要通过标记清除、标记排序和增量标记算法进行回收。主要使用标记清除算法,只有在内存分配不足时,才使用标记排序算法。
首先,使用标记清除完成垃圾空间回收;
通过标记排列优化空间;
使用增量标记来优化效率;
参考文档:
JS垃圾收集机制
垃圾收集机制
摘要
本文到此为止。希望能帮到你,也希望你能多关注我们的更多内容!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。