JS【详解】内存泄漏(含泄漏场景、避免方案、检测方法),垃圾回收 GC (含引用计数、标记清除、标记整理、分代式垃圾回收)

news2024/11/15 22:56:06

内存泄漏

在执行一个长期运行的应用程序时,应用程序分配的内存没有被释放,导致可用内存逐渐减少,最终可能导致浏览器崩溃或者应用性能严重下降的情况,即 JS 内存泄漏

可能导致内存泄漏的场景

  • 不断创建全局变量
  • 未及时清理的闭包:如果闭包中引用了外部的变量,而这个变量又没有被及时释放,就可能发生内存泄漏。
  • DOM元素的引用:如果一个DOM元素被保存在一个JavaScript变量中,但是页面上该DOM元素被移除,这个变量仍然引用着这个DOM元素,导致它无法被垃圾回收。
  • 事件监听器:如果一个DOM元素添加了事件监听器,但在移除该元素之前没有移除事件监听器,则可能发生内存泄漏。
  • 循环引用:两个对象相互引用,导致它们不能被垃圾回收。(现代浏览器改用标记清除的垃圾回收机制,已解决了此问题)

vue 中内存泄漏的场景

组件销毁时未清除全局变量的引用、函数引用、全局事件、自定义事件、定时器。

// 全局变量引用vue实例上的响应式变量
window.list = this.list
// 全局变量引用vue实例上的函数
window.copy = this.copy

如何避免内存泄漏?

  • 避免创建全局变量。
  • 使用严格模式或者let/const声明变量。
  • 及时解除DOM元素的引用。
  • 在移除DOM元素之前,移除相关的事件监听器。
  • 使用弱引用或者引用计数来处理循环引用的问题。(如使用 WeakMap 和WeakSet)
  • 使用工具或者浏览器自带的开发者工具检测和分析内存使用情况,找出潜在的内存泄漏。
  • 编写单元测试以确保内存的正确释放。
  • 使用try/catch/finally来确保资源在异常发生时也能被正确释放。
  • 定期进行垃圾回收(例如在JavaScript中可以使用window.gc()来强制进行垃圾回收,但这不是标准方法,并且不建议在生产环境中使用)。

检测 JS 内存泄漏的方法

可使用浏览器自带的开发者工具

在这里插入图片描述
上图中,HEAP值随时间一直上升,即发生了内存泄漏

正常的内存应该如下图(每隔一段时间,就会进行垃圾回收下降)

在这里插入图片描述

垃圾回收 GC

GC 是垃圾回收(Garbage Collection)的缩写,是由 JavaScript 引擎自动执行的自动内存管理机制,用于检测和清除不再使用的数据,以释放内存空间。

垃圾回收的目的是减少内存泄漏和提高程序的性能。

JS 垃圾回收的算法

引用计数(之前)

通过跟踪每个对象被引用的次数来确定对象是否为垃圾。

逻辑

  • 当一个对象被创建时,其引用计数器初始化为1。
  • 当该对象被其他对象引用时,引用计数器加1。
  • 当该对象不再被其他对象引用时,引用计数器减1。
  • 当引用计数器减至0时,意味着该对象不再被引用,可以被垃圾收集器回收。
// 创建一个对象
let obj = { name: "test" };
// 创建一个引用指向对象
let ref1 = obj;//引用计数+1 1// 创建另一个引用指向对象
let ref2 = obj;//引用计数+1 2// 引用失效
ref1 = null;//引用计数-1 1
ref2 = null;//引用计数-1 0// 引用计数为0,对象可以被回收

优点

  • 实时回收:在对象不再被引用时立即回收,不需要等待垃圾收集器的运行。这可以减少内存占用和提高程序的性能。
  • 简单高效:实现起来相对容易,不需要复杂的算法和数据结构。

缺点

  • 两个或多个对象相互引用时,无法被回收,导致内存泄漏
  • 引用计数需要占用额外的内存空间,而且每次添加、删除引用都需要更新计数,增加了额外的开销。

标记清除(现代)

通过标记不再使用的对象,然后清除这些对象的内存空间,以便后续的内存分配使用。

逻辑

  • 在标记阶段,垃圾回收器会对内存中的所有对象进行遍历,从根对象开始(通常是全局对象)递归地遍历对象的引用关系。对于每个被访问到的对象,垃圾回收器会给它打上标记,表示该对象是可达的,即不是垃圾。
  • 在清除阶段,垃圾回收器会遍历整个内存,对于没有标记的对象,即被判定为垃圾的对象,会被立即回收,释放内存空间。

优点

  • 简单有效:算法相对简单,容易实现
  • 可清除循环引用

缺点

  • 会暂停程序的执行,进行垃圾回收操作。当堆中对象较多时,可能会导致明显的停顿,影响用户体验。
  • 会在回收过程中产生大量的不连续的、碎片化的内存空间。这可能导致后续的内存分配难以找到足够大的连续内存块,从而使得内存的利用率降低。

标记整理(优化)

在标记清除的基础上,增加了整理

逻辑

  • 在标记阶段,标记活动对象
  • 在整理阶段,将内存中的活动对象移动到一端,使得空闲空间连续,并且没有碎片化。
  • 在清除阶段,清除垃圾,回收内存

优点

  • 解决了标记-清除算法产生的碎片化问题,使得内存空间得到更好的利用,减少了空间的浪费。

缺点

  • 会暂停程序的执行,进行垃圾回收操作。当堆中对象较多时,可能会导致明显的停顿,影响用户体验。

V8 引擎的垃圾回收策略

V8是一种由Google开发的用于执行JavaScript 的开源引擎,用于浏览器和Node.js

分代式垃圾回收

将内存划分为新生代(Young Generation)和老生代(Old Generation)两个代:

  • 新生代:存放的是存活时间较短的对象(经过一次垃圾回收后,就被释放回收掉),采用了基于Scavenge算法的快速垃圾回收策略,通过将内存分为两个半空间来进行垃圾回收,优化了对象的分配和回收过程。
  • 老生代:存放的是存活时间较长的对象(经过多次垃圾回收后仍存在),采用了基于标记-整理-清除算法的全垃圾回收策略,通过对整个堆进行标记和整理,以减少内存的碎片化,提高内存利用率。

更多详情可参考
https://zhuanlan.zhihu.com/p/689678104

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1971264.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Graylog 收集网络设备日志的详细配置指南

需求:网络日志接入到日志服务中,做日志的备份和查询。 交换机或是其它网络设备日志需要接入到graylog日志服务中进行备份和查询。 软件版本 graylog5.1 架构图 一、添加inputs 接受日志信息 二、编辑inputs 配置 第1个红框 title 代表通道的名称,您可以根据需要自由定义…

【CTF-Crypto】格密码基础(例题较多,非常适合入门!)

格密码相关 文章目录 格密码相关格密码基本概念(属于后量子密码)基础的格运算(行列式运算)SVP(shortest Vector Problem)最短向量问题CVP(Closet Vector Problem)最近向量问题 做题要…

浏览器用户文件夹详解 - ShortCuts(六)

1. Shortcuts简介 1.1 什么是Shortcuts文件? Shortcuts文件是Chromium浏览器中用于存储用户创建的快捷方式信息的一个重要文件。每当用户在浏览器中创建快捷方式时,这些信息都会被记录在Shortcuts文件中。通过这些记录,用户可以方便地快速访…

《小迪安全》学习笔记02

域名默认存放目录和IP默认存放目录不一样。 IP地址是WWW文件里的,域名访问是WWW里的一个子目录里的(比如是blog)。 Nmap: Web源码拓展 拿到一个网站的源码,要分析这几个方面↑。 不同类型产生的漏洞类型也不一样 在网站中&…

MSPM0G3507_2024电赛自动行驶小车(H题)_问题与感悟

这次电赛题目选的简单了,还规定不能使用到摄像头,这让我之前学习的Opencv 4与树莓派无用武之地了,但我当时对于三子棋题目饶有兴趣,但架不住队友想稳奖,只能选择这个H题了...... 之后我还想抽空将这个E题三子棋题目做…

快手批量取关

目录 突然发现快手木有批量取关功能,没有功能就创造功能 执行代码中 逐渐变少 后面关注列表没人了,总数还有32,不知道是不是帮测出个bug还是咋的(^_^) 突然发现快手木有批量取关功能,没有功能就创造功能 刚开始1000多人 执行代…

中间件之异步通讯组件rocketmq入门

一、概述 1.1介绍 RocketMQ是阿里巴巴2016年MQ中间件,使用Java语言开发,RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域&#…

暖水袋 亚马逊日本站认证 PSE认证步骤

暖水袋是用来加热取暖的生活用品,有内置热水来加热的类型和利用微波炉加热后使用的类型等。内置热水的暖水袋有塑料制、橡胶制、陶器制等多种类型,但是利用加热石头而不是利用热水来取暖的产品类型为审查对象外商品。 审查资料 每个 ASIN 的文件&#x…

成为AI产品经理,为何应选择LLMs方向?

前言 随着人工智能(AI)技术的快速发展,越来越多的人开始考虑如何在这个领域找到自己的位置。对于那些希望成为AI产品经理的人来说,选择LLMs(Large Language Models,大型语言模型)方向是一个非常…

mac下通过brew安装mysql的环境调试

mac安装mysql 打开终端,运行命令(必须已经装过homebrew哦): 安装brewbin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"已安装brew直接运行:brew install mysql8.0报…

模拟自然光照:饮料稳定性测试的创新方法

饮料添加剂的光照稳定性测试旨在评估其在光照影响下的保持稳定性的能力,特别是在储存期间。此测试有助于制造商理解饮料在不同光源作用下的变化,例如颜色、口感、香气等感官性质的变化,以及营养成分的衰变速率。这些信息对改进产品配方、包装…

泉盛UV-K5/K6固件编译教程

0.准备的硬件 win11/win10电脑泉盛UV-K5/K6k口写频线 1.准备的文件(点击链接下载) gcc arm编译器 链接: gcc-arm-none-eabi-10.3-2021.10-win32Make 链接:Download make-3.81.exe (GnuWin) 2.编译过程(这里以Losehu固件为例子) 0.…

AI时代的职场焦虑与机遇

原文链接:https://tecdat.cn/?p37205 在人工智能的浪潮中,职场焦虑愈发显著。本杰明米勒的故事便是这一现象的缩影。2023年初,他领导着一个超过60人的团队,为一家科技公司创作推广文章和博客。然而,随着公司决定采用…

排序算法:插入排序,golang实现

目录 前言 插入排序 代码示例 1. 算法包 2. 插入排序代码 3. 模拟程序 4. 运行程序 5. 从大到小排序 插入排序的思想 循环细节 外层循环 内层循环 循环次数测试 假如 10 条数据进行排序 假如 20 条数据进行排序 假如 30 条数据进行排序 假设 5000 条数据&…

Elasticsearch服务器开发教程(第2版 电子版)

前言 本书也将讨论被称为Querydsl的查询语言,通过它可以创建复杂的查询并过滤返回的结果。除了这些,你还将看到如何使用切面技术(faceting)基于查询结果来计算汇总数据,以及如何使用新引进的聚合框架(分析…

云计算 Logstash 配置管理 Kibana数据统计分析

日志分析系统ELK 项目架构图 Logstash 是一个开源的、服务器端的数据收集引擎,与 Elasticsearch 和 Kibana 一起构成了 Elastic Stack(之前称为 ELK Stack)。Logstash 的主要功能是处理和转发数据,它可以从多种数据源收集数据&a…

Autowired自动注入Map问题

问题 昨天开发的时候遇到一个诡异的问题,通过Map注入接口下所有的子类,然后json打印出来的时候,没有子类的信息,并且去调用的时候报了空指针异常。 排查问题过长,并且涉及到源码,所以这里先说结论&#x…

2018-架构师案例(七)

问题1 性能需求指什么? 解析: 指响应时间,吞吐量,资源利用率等指标,保证系统正常运行的情况下,这些数据表示系统的性能。 问题2(9分) MemCache和Redis两种工具的优缺点&#xff0c…

js 前端 解析excel文件【.xlsx文件】信息内容

需求&#xff1a; 从excel文件中解析里面的内容 1、使用插件xlsx.full.min.js&#xff0c;地址&#xff1a;https://unpkg.com/xlsx/dist/xlsx.full.min.js实例&#xff1a; <script src"https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script><i…

【机器学习基础】数据预处理

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…