资讯专栏INFORMATION COLUMN

简述JavaScript的垃圾回收机制

wenshi11019 / 1232人阅读

摘要:关键是释放内存这一步,各种语言都有自己的垃圾回收简称机制。用的是这种,在字末位进行标识,为指针。对于而言,最初的垃圾回收机制,是基于引用计次来做的。老生代的垃圾回收,分两个阶段标记清理有和这两种方式。

不管是高级语言,还是低级语言。内存的管理都是:

分配内存

使用内存(读或写)

释放内存

前两步,大家都没有太大异议。关键是释放内存这一步,各种语言都有自己的垃圾回收(garbage collection, 简称GC)机制。做GC的第一步是判断堆中存的是数据还是指针,是指针的话,说明它被指向活跃的对象。有3种判断方法:

Conservative:如果存储格式是地址,就认为是。C/C++有用到这种算法。

Compiler hints:对于静态语言,比如Java,编译器是知道它是不是指针的,所以可以用这种。

Tagged pointers:JavaScript用的是这种,在字末位进行标识,1为指针。

对于JavaScript而言,最初的垃圾回收机制,是基于引用计次来做的。后来升级为标记清除。

引用计次

当对象被引用次数为0时,就被回收。潜在的一个问题是:循环引用时,两个对象都至少被引用了一次,将不能自动被回收。所以导致,我们常讲的内存泄露。

// 引用计次
var a = {t: 1}; // 对象 `{t: 1}` (以下简称obj)被引用一次
var b = a; // obj 被引用两次
a = null; // obj 现在为1次
b = null; // obj 现在为0次,可回收

// 循环引用
function fn() {
    var a = {};
    var b = {};
    a.b = b;
    b.a = a;
}

fn();
标记清除

这是当前主流的GC算法,V8里面就是用这种。当对象,无法从根对象沿着引用遍历到,即不可达(unreachable),进行清除。对于上面的例子,fn() 里面的 ab 在函数执行完毕后,就不能通过外面的上下文进行访问了,所以就可以清除了。

下面,我们简述下V8的GC机制:

V8的GC机制

在大部分的应用场景:一个新创建的对象,生命周期通常很短。所以,V8里面,GC处理分为两大类:新生代和老生代。

新生代的堆空间为1M~8M,而且被平分成两份(to-space和from-space),通常一个新创建的对象,内存被分配在新生代。当to-space满的时候,to-space和form-space交换位置(此时,to空,from满),并执行GC.如果一个对象被断定为,未被引用,就清除;有被引用,逃逸次数+1(如果此时逃逸次数为2,就移入老生代,否则移入to-space)。

老生代的堆空间大,GC不适合像新生代那样,用平分成两个space这种空间换时间的方式。老生代的垃圾回收,分两个阶段:标记、清理(有Sweeping和Compacting这两种方式)。

标记,采用3色标记:黑、白、灰。步骤如下:

GC开始,所以对象标记为白色。

根对象标记为黑色,并开始遍历其子节点(引用的对象)。

当前被遍历的节点,标记为灰色,被放入一个叫 marking bitmap 的栈。在栈中,把当前被遍历的节点,标记为黑色,并出栈,同时,把它的子节点(如果有的话)标记为灰色,并压入栈。(大对象比较特殊,这里不展开)

当所有对象被遍历完后,就只剩下黑和白。通过Sweeping或Compacting的方式,清理掉白色,完成GC。

小补充:JavaScript的根对象

GC的时候,从根对象开始遍历。在浏览器,根对象是 window;在 Node.js 中,是 global(或称为root).

Node.js中,每个文件被当做一个模块,所以,当你用 var/let/const 在文件的全局,声明变量的时候,作用域是当前文件(模块)。因此,图中 root.aundefined.

Links:

Memory Management

What is the root object in Node.js

解读 V8 GC Log(一): Node.js 应用背景与 GC 基础知识

解读 V8 GC Log(二): 堆内外内存的划分与 GC 算法

A tour of V8: Garbage Collection

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88482.html

相关文章

  • 手撕面试官系列(十一):BAT面试必备之常问85题

    摘要:什么是线程饿死,什么是活锁多线程中的忙循环是什么变量是什么变量和变量有什么不同类型变量提供什么保证能使得一个非原子操作变成原子操作吗 JVM专题 showImg(https://segmentfault.com/img/remote/1460000019943435); (面试题+答案领取方式见个人主页) Java 类加载过程? 描述一下 JVM 加载 Class 文件的原理机制? ...

    Hwg 评论0 收藏0
  • 手撕面试官系列(十一):BAT面试必备之常问85题

    摘要:什么是线程饿死,什么是活锁多线程中的忙循环是什么变量是什么变量和变量有什么不同类型变量提供什么保证能使得一个非原子操作变成原子操作吗 JVM专题 showImg(https://segmentfault.com/img/remote/1460000019943435); (面试题+答案领取方式见个人主页) Java 类加载过程? 描述一下 JVM 加载 Class 文件的原理机制? ...

    CatalpaFlat 评论0 收藏0
  • 前端20个真正灵魂拷问,吃透这些你就是中级前端工程师 【上篇】

    摘要:还是老规矩,从易到难吧传统的定时器,异步编程等。分配对象时,先是在空间中进行分配。内存泄漏内存泄漏是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 showImg(https://segmentfault.com/img/bVbwkad?w=1286&h=876); 网上参差不弃的面试题,本文由浅入深,让你在...

    mdluo 评论0 收藏0
  • 前端20个真正灵魂拷问,吃透这些你就是中级前端工程师 【上篇】

    摘要:还是老规矩,从易到难吧传统的定时器,异步编程等。分配对象时,先是在空间中进行分配。内存泄漏内存泄漏是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 showImg(https://segmentfault.com/img/bVbwkad?w=1286&h=876); 网上参差不弃的面试题,本文由浅入深,让你在...

    leap_frog 评论0 收藏0
  • G1垃圾收集器简述

    摘要:垃圾收集器简述全文共两部分有基础的读者只需要阅读第一部分垃圾收集器在最新几个版本的发展第二部分为基础部分垃圾收集器在最新几个版本的发展垃圾收集器始见于版本在后续的几个版本中对它进行了优化和改进在中垃圾收集器增加了几个可配置选项的自动发现功能 G1垃圾收集器简述 全文共两部分,有基础的读者只需要阅读第一部分G1垃圾收集器在最新几个版本的发展,第二部分为基础部分. G1垃圾收集器在最新几个...

    honhon 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<