,,详解JavaScript的垃圾回收机制

,,详解JavaScript的垃圾回收机制

本文主要介绍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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: