浏览器工作原理与实践
李兵
前盛大创新院高级研究员
56402 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 46 讲
浏览器工作原理与实践
15
15
1.0x
00:00/00:00
登录|注册

13 | 垃圾回收:垃圾数据是如何自动回收的?

标记-整理算法
标记-清除算法
对象晋升策略
Scavenge算法
增量标记算法
主垃圾回收器
副垃圾回收器
JavaScript、Java、Python等语言的自动回收策略
C/C++的手动回收策略
全停顿
垃圾回收器的工作流程
代际假说和分代收集
ESP指针的作用
执行流程分析
自动回收
手动回收
引用类型数据存储在堆空间
原始数据类型存储在栈空间
工作中避免内存泄漏的方法
判断JavaScript中内存泄漏的方法
工程师的视角
垃圾回收策略的权衡
堆中的数据回收
调用栈中的数据回收
垃圾数据的回收策略
JavaScript中的数据存储方式
思考时间
总结
JavaScript中的垃圾数据回收
垃圾数据的自动回收
垃圾回收

该思维导图由 AI 生成,仅供参考

上一篇文章中,我们提到了 JavaScript 中的数据是如何存储的,并通过例子分析了原始数据类型是存储在栈空间中的,引用类型的数据是存储在堆空间中的通过这种分配方式,我们解决了数据的内存分配的问题。
不过有些数据被使用之后,可能就不再需要了,我们把这种数据称为垃圾数据。如果这些垃圾数据一直保存在内存中,那么内存会越用越多,所以我们需要对这些垃圾数据进行回收,以释放有限的内存空间

不同语言的垃圾回收策略

通常情况下,垃圾数据回收分为手动回收自动回收两种策略。
如 C/C++ 就是使用手动回收策略,何时分配内存、何时销毁内存都是由代码控制的,你可以参考下面这段 C 代码:
//在堆中分配内存
char* p = (char*)malloc(2048); //在堆空间中分配2048字节的空间,并将分配后的引用地址保存到p中
//使用p指向的内存
{
//....
}
//使用结束后,销毁这段内存
free(p);
p = NULL
从上面这段 C 代码可以看出来,要使用堆中的一块空间,我们需要先调用 mallco 函数分配内存,然后再使用;当不再需要这块数据的时候,就要手动调用 free 函数来释放内存。如果这段数据已经不再需要了,但是又没有主动调用 free 函数来销毁,那么这种情况就被称为内存泄漏
另外一种使用的是自动垃圾回收的策略,如 JavaScript、Java、Python 等语言,产生的垃圾数据是由垃圾回收器来释放的,并不需要手动通过代码来释放。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

JavaScript中的垃圾数据回收机制是通过副垃圾回收器和主垃圾回收器来实现的。副垃圾回收器主要负责新生区的垃圾回收,采用Scavenge算法将新生代空间对半划分为对象区域和空闲区域,通过复制和角色翻转完成垃圾数据的回收。而主垃圾回收器则负责老生区的垃圾回收,采用标记-清除和标记-整理算法来处理大对象和长生命周期对象的回收。在执行垃圾回收时,由于JavaScript运行在主线程上,会导致全停顿现象,影响应用的性能和响应能力。为了降低全停顿的影响,V8引擎采用增量标记算法来分解垃圾回收任务,使其与JavaScript应用逻辑交替执行,从而减少页面卡顿现象。总的来说,JavaScript中的垃圾数据回收机制涉及多种算法和策略,需要在满足需求的前提下进行权衡,以适应最核心的需求。文章通过深入浅出的方式介绍了JavaScript中垃圾数据的自动回收机制,为读者提供了全面的技术视角和思考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《浏览器工作原理与实践》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(92)

  • 最新
  • 精选
  • mfist
    1. 如何判断内存泄漏的?一般是感官上的长时间运行页面卡顿,猜可能会有内存泄漏。通过DynaTrace(IE)profiles等工具一段时间收集数据,观察对象的使用情况。然后判断是否存在内存泄漏。修改后验证 2. 工作中避免内存泄漏方法:确定不使用的临时变量置为null,当前es6普及场景下少使用闭包也是一种方法。 今日总结 垃圾回收策略一般分为手动回收和自动回收,java python JavaScript等高级预言为了减轻程序员负担和出错概率采用了自动回收策略。JavaScript的原始类型数据和引用数据是分别存储在栈和椎中的,由于栈和堆分配空间大小差异,垃圾回收方式也不一样。栈中分配空间通过ESP的向下移动销毁保存在栈中数据;堆中垃圾回收主要通过副垃圾回收器(新生代)和主垃圾回收器(老生代)负责的,副垃圾回收器采用scavenge算法将区域分为对象区域和空闲区域,通过两个区域的反转让新生代区域无限使用下去。主垃圾回收器采用Mark-Sweep(Mark-Compact Incremental Marking解决不同场景下问题的算法改进)算法进行空间回收的。无论是主副垃圾回收器的策略都是标记-清除-整理三个大的步骤。另外还有新生代的晋升策略(两次未清除的),大对象直接分配在老生代。

    作者回复: 总结很好,还可以通过Chrome开发者工具中的Performance来观察。

    2019-09-03
    122
  • Hurry
    使用 chrome 的 Performance 面板,观察内存变化 如何多次垃圾回收后,整体趋势是向上,就存在内部泄漏的可能!

    作者回复: 这是一个很好的方法

    2019-09-03
    3
    25
  • 对于栈中的垃圾回收,是通过移动 ESP 指针来实现的,是不需要通过V8的垃圾回收机制的吗?

    作者回复: 是的 栈中的过期数据直接通过esp给抹掉,效率非常高。

    2019-09-03
    3
    24
  • 对于新生代,副垃圾回收器是怎么进行标记的,文章也就一句话带过了,是和老生代标记算法一样吗?从一组跟元素开始,然后开始遍历的

    作者回复: 新生区和老生区标记过程是同一个过程,之后新生代把存活的数据移动到空闲区,老生代把死去的对象加到空闲列表中。

    2019-09-03
    2
    22
  • 芒果
    大道至简,看完了浏览器的垃圾回收,让我联想到了jvm的垃圾回收,发现2者思想上基本都差不多。

    作者回复: 现代虚拟机都是抄来抄去的

    2019-11-06
    2
    21
  • 屈悦微
    这篇文章写得很有深度,反复看了几遍,收获颇多,但是仍有一个问题,望作者百忙之中能解答 在本篇中作者介绍了的垃圾回收机制是,标记对象的机制 但在《javascript高级程序设计》中还介绍了引用计数的机制 我产生以下两个疑问 1.v8有没有使用引用计数的机制? 2.如果有,何时使用引用计数,何时使用标记对象?

    作者回复: 引用计数有问题,会导致内存泄漏,所以现在流行的垃圾回收器都没有采用引用计数的方式!

    2019-12-06
    17
  • 郝仁杰
    trim之后,数据在堆上的地址发生变化,v8是如何更新对应栈上的引用的

    作者回复: JavaScript中的原始字符串是不可变的(immutable),也就是说,一旦一个字符串创建了,它在内存中的值就不可能改变,这和其他语言是有区别的。 所以当你调用trim方法后,v8引擎返回给你的是一个新字符串,并不是之前的字符串了。

    2019-09-03
    7
    16
  • 咖飞的白
    请教老师几个问题: 1. JS 执行代码时是在执行声明语句时就分配内存还是赋值时分配?若是执行声明语句时就分配,那如何知道是大对象(存储在老生代)还是新对象(存储在新生代)?

    作者回复: 声明变量是在编译阶段完成的,这时赋值语句还没执行! 比如 var a = 6 首先编译阶段确定有变量a了,并给a赋值undefined; 接下来执行代码,在执行过程中,会将6赋给a,这时候a等于6! 由于6是原生类型,通常情况下,会在栈上分配该变量! 如果 var a = Object 将对象赋给a时,在编译阶段 a依然等于undefined,在执行过程中,会在堆中创建一块内存,存放Object的值,然后栈中有个指向堆中Object地址的指针

    2020-01-13
    15
  • tick
    标记的过程具体是什么样的呢?我理解老师讲的是,一个指针指向堆里,每次移动一块内存,一个指针遍历栈中,然后看栈中是否引用这块堆中的内存,但感觉这样效率很低

    作者回复: 比如全局window对象看成是一个树状结构,垃圾回收时,V8会先遍历这颗树,能遍历到的元素说明还存活的,标记为活动对象!没有被标记到的说明已经没有被引用了。 同时V8还维护了一个空闲列表,也就是没有被使用的空闲空间列表,垃圾清理过程就是把没有标记的添加到空闲列表中! 这样就完成了“标记-清除”操作

    2019-09-03
    2
    12
  • 于你
    老师,我最近听了一门课,那个老师说现代的浏览器用闭包不会造成内存泄漏,因为垃圾回收是用的标记清除

    作者回复: 对,没有被引用的闭包会被自动回收,不过如果没用的闭包还保存在全局变量中,依然会内存泄漏!

    2019-09-07
    5
    11
收起评论
显示
设置
留言
92
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部