美文网首页
垃圾回收

垃圾回收

作者: 达文西_Huong | 来源:发表于2020-06-18 16:41 被阅读0次

js的垃圾回收

原文:https://segmentfault.com/a/1190000018605776


垃圾回收

JavaScript 中的内存管理是自动执行的,而且是不可见的。我们创建基本类型,对象,函数...所有这些都需要内存。

当不再需要某样东西的时候会发生什么? JavaScript 引擎是如何发现并清理它?

可达性

JavaScript 中内存管理的主要概念是可达性。

简单地说,可达性值就是那些以某种方式可访问或可用的值,它们被保证存储在内存中。

1. 有一组基本的固有可达值,由于显而易见的原因无法删除。例如:

  • 本地函数的局部变量和参数
  • 当前嵌套调用链上的其他函数的变量和参数
  • 全局变量

这些值称为

2. 如果引用或引用链可以从根访问任何其它值,则认为该值是可访问的

例如,如果局部变量中有对象,并且该对象具有引用另一个对象的属性,则该对象被视为可达性,它引用的那些也是可以访问的,详细的例子如下

JavaScript 引擎中有一个后台进程称为垃圾回收器,他监视所有对象,并删除那些不可访问的对象

一个简单的例子

    // user 具有对象的引用
    let user = {
        name:"John"
    }
image

这里箭头表示一个对象引用。全局变量user引用对象{name:john}(为了简洁表达,我们称为john)。
John 的name属性存储一个基本类型,因此他被绘制在对象中。

如果user的值被覆盖,则引用丢失:

    user = null
image

现在John 变成不可到达的状态,没有办法访问它,没有对它的引用。垃圾回收器将丢弃 John 数据,并且释放内存

两个引用

现在让我们假设我们将引用从user 复制到 admin

    // user 具有对象引用
    let user = {
        name:"john"
    };

    let admin = user;
image

现在如果我们做同样的事情

    user = null;

该对象仍然可以通过admin全局变量访问,所以它在内存中。如果我们也覆盖admin,那么它也可以被释放。

相互关联的对象

现在来看一个更复杂的例子,family 对象

    function marry(man,women) {
        women.husban = man;
        man.wife = women;

        return {
            father: man,
            mother: women
        }
    }

    let family = marry({
        name:"john"
    },
    {
        name:"Ann"
    })

函数marry通过给两个对象彼此提供引用来"联姻"它们,并返回一个包含两个对象的新对象产生的内存结构:

image

到目前为止,所有对象都是可访问的。

现在让我们删除两个引用

    delete family.father;
    delete family.mother.husband
image

仅仅删除这两个引用中的一个是不够的,因为所有对象仍然可以访问的。

但是如果我们把这两个都删除,那么我们可以看到 John 不再具有传入的引用

image

输出引用无关紧要。只有传入的对象才能使对象可访问,因此, john现在是不可访问的,并将从内存中删除所有不可访问的数据。

垃圾回收之后:

image

无法访问的数据块

可有可能整个相互连接的对象变得不可访问并从内存中删除。

源对象与上面相同,然后:

    family = null

内存中的图片变成:

image

这个例子说明了可达性的概念是多么重要。

很明显,john 和 Ann 仍然连接在一起,都有引入的引用。但这不够。

family 对象已经从根上断开连接了,不再有对它的引用,因此下面的整个块变得不可到达,并将删除。

内部算法

基本的垃圾回收算法称为标记-清除,定期执行以下垃圾回收步骤:

  • 垃圾回收器获取根并标记它们。
  • 然后它访问并标记所有来自它们的引用
  • 然后他访问标记的对象并标记它们的引用。所有访问的对象都被记住,以便以后不再访问同一个对象两次。
  • 以此类推,直到有未访问的引用(可以从根访问)为止。
  • 除标记的对象外,所有对象都被删除。

例如,对象结构如下:

image

我们可以清除地看到右边有一个 “不可到达的块”。现在让我们看看标记并清除垃圾回收器如何处理它

第一步标记根

image

然后标记它们的引用

image

以及子孙代的引用:

image

现在进程中不能访问的对象被认为不可访问的,将被删除

image

这就是垃圾收集的工作原理。JavaScript 引擎应用了许多优化,使其运行得更快,并且不影响执行。

一些优化:

  • 分代回收 ———— 对象分为两组:"新对象" 和"旧对象"。许多对象出现,完成它们的工作并迅速结束,它们很快就会被清理干净。那些活得足够久的对象,会变"老" ,并且很少接受检查。

  • 增量回收 ———— 如果有很多对象,并且我们试图一次遍历并标记整个对象集,那么可能会花费一些时间,并在执行中会有一定延迟。因此,引擎试图将垃圾回收分为多个部分。然后,各个部分分别执行。这需要额外的标记来跟踪变化,这样有很多微小的延迟,而不是很大的延迟。

  • 空闲时间收集 ———— 垃圾回收器只在 CPU 空闲时运行,以减少对执行的可能影响。

总结

什么是垃圾

一般来说没有被引用的对象就是垃圾,就要被清除。如果有多个对象互相引用,但是并不能访问到它们,那它们也算是垃圾,也要被清除。

如何捡垃圾

一种算法是标记-清除算法。就是每次都会从根开始依次标记对应的引用,在进程中不能访问的对象就会当作垃圾清除。


以上

相关文章

  • 简单理解垃圾回收

    什么是垃圾回收? 垃圾回收的是什么? 如何判断为垃圾? 垃圾是怎样被回收的? 垃圾回收哪些区域的内存? 什么是垃圾...

  • JVM(二) GC算法与分代回收策略

    可达性分析 GCRoot场景 垃圾回收算法 分代回收策略 引用 垃圾回收 垃圾回收(Garbage Collect...

  • JVM调优之垃圾定位、垃圾回收算法、垃圾处理器对比

    谈垃圾回收器之前,要先讲讲垃圾回收算法,以及JVM对垃圾的认定策略,JVM垃圾回收器是垃圾回收算法的具体实现,了解...

  • 01垃圾回收机制

    垃圾回收(Garbage Collection,GC) 垃圾回收就是释放垃圾占用的空间 内存的动态分配和垃圾回收,...

  • Java 垃圾收集(GC)浅谈

    Java 垃圾收集(GC)浅谈 为什么需要垃圾回收?哪些内存需要回收?什么时候回收?如何回收? 为什么需要垃圾回收...

  • JVM垃圾回收机制

    JVM垃圾回收 整体思维导图 带着问题理解JVM垃圾回收机制 Java为什么需要垃圾回收机制; 回收哪部分垃圾; ...

  • 垃圾回收

    如何查看当前JVM使用的垃圾回收器? 如何指定使用CMS回收? 如何打印回收日志? 垃圾回收过程 CMS垃圾回收的...

  • JVM常见垃圾回收器介绍

    垃圾回收器简介 在新生代和老年代进行垃圾回收的时候,都是要用垃圾回收器进行回收的,不同的区域用不同的垃圾回收器。分...

  • JavaScript的垃圾回收机制

    大纲 1、认识垃圾回收机制2、垃圾回收机制的原理3、垃圾回收机制的标记策略4、垃圾回收机制与内存管理 1、认识垃圾...

  • 一文带你深入了解JVM性能调优以及对JVM调优的全面总结

    目录 JVM调优 概念 基本垃圾回收算法 垃圾回收面临的问题 分代垃圾回收详述1 分代垃圾回收详述2 典型配置举例...

网友评论

      本文标题:垃圾回收

      本文链接:https://www.haomeiwen.com/subject/hzksxktx.html