宝哥软件园

JavaScript中内存泄漏的介绍和教程(推荐)

编辑:宝哥软件园 来源:互联网 时间:2021-09-04

本文主要详细介绍了JavaScript中内存泄漏的相关内容,非常详细,对大家有一定的参考价值。我们来看看详细的介绍:

1.什么是内存泄漏?

程序需要内存才能运行。只要程序请求它,操作系统或运行时就必须提供内存。

对于连续运行的服务进程(守护进程),必须及时释放不再使用的内存。否则,内存占用越来越高,不仅会影响系统性能,还会导致进程崩溃。

不再使用的内存,如果不及时释放,称为内存泄漏。

有些语言(如C语言)必须手动释放内存,由程序员负责内存管理。

char *缓冲区;buffer=(char *)malloc(42);//用bufferfree(缓冲区)做点什么;以上是C语言代码。malloc方法用于申请内存。使用后,必须使用free方法释放内存。

这是非常麻烦的,所以大多数语言都提供自动内存管理来减轻程序员的负担,这就是所谓的垃圾收集器。

二、垃圾收集机制

垃圾收集机制如何知道哪些内存不再需要?

最常用的方法叫做“引用计数”:语言引擎有一个“引用表”,它保存内存中所有资源(通常是各种值)的引用次数。如果某个值的引用次数为0,则表示该值不再使用,因此可以释放内存。

在上图中,左下角的两个值没有引用,可以释放。

如果不再需要某个值,但引用数不为0,垃圾收集机制将无法释放该内存,从而导致内存泄漏。

const arr=[1,2,3,4];console . log(' hello world ');在上面的代码中,数组[1,2,3,4]是一个值,它将占用内存。变量arr是对该值的唯一引用,因此引用数为1。虽然在下面的代码中没有使用arr,但是它将继续占用内存。

如果您添加一行代码,并删除arr对[1,2,3,4]的引用,则可以通过垃圾收集机制释放这些内存。

让arr=[1,2,3,4];console . log(' hello world ');arr=null在上面的代码中,当arr复位为null时,对[1,2,3,4]的引用被取消,引用数变为0,可以释放内存。

因此,并不意味着程序员会对垃圾收集机制放松。您仍然需要注意内存使用:一旦不再使用这些值,您必须检查是否还有对它们的引用。如果是,必须手动取消引用。

三、内存泄漏的识别方法

如何观察内存泄漏?

经验法则是,如果连续五次垃圾回收后,每次内存占用都比较大,就会出现内存泄漏。这需要实时查看内存使用情况。

3.1浏览器

Chrome浏览器要检查内存使用情况,请按照以下步骤操作。

打开开发人员工具,选择时间线面板,在顶部的捕获字段中选中内存,然后单击左上角的录制按钮。在页面上执行各种操作来模拟用户的使用情况。一段时间后,点击对话框中的停止按钮,该段时间的内存使用情况会显示在面板上。如果内存占用率基本稳定,接近水平,说明没有内存泄漏。

相反,这是内存泄漏。

3.2命令行

命令行可以使用Node提供的process.memoryUsage方法。

console . log(process . memoryusage());//{rss: 27709440,//heaptotal3360 5685248,//heapused: 349392,//external3360 8772}进程。memoryusage返回一个包含节点进程内存使用信息的对象。这个对象包含四个字节的字段,意思如下。

Rss(常驻集大小):所有内存占用,包括指令区和堆栈。HeapTotal:由“堆”占用的内存,包括已使用和未使用的内存。堆:堆中被使用的部分。外部:V8引擎内部C对象占用的内存。基于heapUsed字段判断内存泄漏。

第四,WeakMap

如前所述,及时清除引用非常重要。然而,你记不起那么多了。有时候忽略了就忘了,所以内存泄漏这么多。

最好有一种方法来声明在创建新引用时哪些引用必须手动清除,哪些引用可以忽略。当其他引用消失时,垃圾收集机制可以释放内存。这样可以大大减轻程序员的负担,只需要清除主要引用即可。

鉴于此,ES6引入了两种新的数据结构:WeakSet和WeakMap。它们对值的引用不包含在垃圾收集机制中,因此名称中有一个“Weak”,表示它是一个弱引用。

让我们以WeakMap为例,看看它是如何解决内存泄漏的。

const WM=new WeakMap();const element=document . getelementbyid(' example ');wm.set(元素,“某些信息”);在上面的代码中,首先创建一个Weakmap实例。然后,一个DOM节点作为键名存储在实例中,一些附加信息作为键值一起存储在WeakMap中。此时,对WeakMap中元素的引用是一个弱引用,在垃圾收集机制中不会被计算在内。

也就是说,DOM节点对象的引用计数是1,而不是2。此时,一旦对该节点的引用被消除,其占用的内存将被垃圾回收机制释放。Weakmap保存的键值对也会自动消失。

基本上,如果您想在不干扰垃圾收集机制的情况下向对象添加数据,可以使用WeakMap。

动词(verb的缩写)WeakMap示例

WeakMap的例子很难演示,因为无法观察到其中的引用会自动消失。此时,所有其他引用都已取消,指向WeakMap的键名也未被引用,无法确认该键名是否存在。

我一直想不出办法,直到有一天,何老师建议,如果引用所指向的值占用大量内存,可以通过process.memoryUsage方法查看。

根据这个想法,用户vtxf添加了以下示例。

首先,打开节点命令行。

$ node - expose-gc在上面的代码中,- expose-gc参数表示允许手动垃圾收集机制。

然后,执行以下代码。

//手动执行垃圾收集,确保获取的内存使用状态是准确的global . GC();Undefined//检查内存使用的初始状态,heapUsed约为4M。process . memoryusage();{ rss: 21106688,heapTotal: 7376896,heapUsed: 4153936,external : 9059 } let WM=new WeakMap();未定义的字母b=新对象();undefined global . GC();Undefined//此时heapUsed还是4M左右。process . memoryusage();{RSS : 20537344,堆总数: 9474048,堆已用3360 3967272,外部3360 8993 }//在WeakMap中添加键值对。//键名为对象B,键值为数组WM。5*1024*1024一套。WeakMap {}//手动执行垃圾收集全局. GC();Undefined//此时heapUsed约为45M。process . memoryusage();{rss: 62652416,heaptotal3360 51437568,heapused 3360 45911664,external : 8951 }//取消引用对象b=nullNull//再次执行垃圾收集global . GC();undefined//b被解引用后,heapUsed变回约4M//,这意味着WeakMap中长度为5*1024*1024的数组已经被process.memoryUsage()销毁;{RSS : 20639744,Heap Total : 8425472,Heap Used 3360 397992,External 3360 8956}在上面的代码中,只要外部引用消失,WeakMap的内部引用就会被垃圾回收自动清除。因此,在它的帮助下,解决内存泄漏会容易得多。

不及物动词参考链接

在node.js中查找JavaScript内存泄漏的简单指南了解垃圾收集和搜索node.js中的内存泄漏调试node.js应用程序中的内存泄漏摘要

以上就是本文的全部内容。希望本文的内容能给你的学习或工作带来一些帮助。有问题可以留言交流。谢谢你的支持。

更多资讯
游戏推荐
更多+