JS【详解】内存泄漏(含泄漏场景、避免方案、检测方法),垃圾回收 GC (含引用计数、标记清除、标记整理、分代式垃圾回收)
内存泄漏
在执行一个长期运行的应用程序时,应用程序分配的内存没有被释放,导致可用内存逐渐减少,最终可能导致浏览器崩溃或者应用性能严重下降的情况,即 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
相关文章:

JS【详解】内存泄漏(含泄漏场景、避免方案、检测方法),垃圾回收 GC (含引用计数、标记清除、标记整理、分代式垃圾回收)
内存泄漏 在执行一个长期运行的应用程序时,应用程序分配的内存没有被释放,导致可用内存逐渐减少,最终可能导致浏览器崩溃或者应用性能严重下降的情况,即 JS 内存泄漏 可能导致内存泄漏的场景 不断创建全局变量未及时清理的闭包&…...

第三期书生大模型实战营之Llamaindex RAG实践
基础任务 任务要求:基于 LlamaIndex 构建自己的 RAG 知识库,寻找一个问题 A 在使用 LlamaIndex 之前InternLM2-Chat-1.8B模型不会回答,借助 LlamaIndex 后 InternLM2-Chat-1.8B 模型具备回答 A 的能力,截图保存。 streamlit界面…...
【从0到1进阶Redis】Jedis 理解事务
笔记内容来自B站博主《遇见狂神说》:Redis视频链接 小伙伴们可以熟悉一下本专栏的 Redis 文章,可以更好地理解 正常操作 package oldfe.study;import com.alibaba.fastjson.JSONObject; import redis.clients.jedis.Jedis; import redis.clients.jedis.T…...
MySQL之Lost connection to MySQL server during query复现测试
测试Lost connection to MySQL server during query复现条件 环境报错信息复现测试方式一方式二 环境 Python: 3.8/3.9 Mysql: 5.x 报错信息 File "/Users/xxx/lib/python3.9/site-packages/sqlalchemy/dialects/mysql/base.py", line 2509, in do_rollbackdbapi_con…...

中国AI大模型场景探索及产业应用调研报告
AI大模型发展态势 定义 AI大模型是指在机器学习和深度学习领域中,采用大规模参数(至少在一亿个以上)的神经网络模型,AI大模型在训练过程中需要使用大量的算力和高质量的数据资源。 产业规模 2023年,中国大模型市场规模为147亿。结合《202…...

Linux--shell脚本语言—/—<1>
一、shell简介 Shell是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构&am…...
【java框架开发技术点】通过反射机制调用类中的私有或受保护的方法
示例 假设我们有一个类 ExampleClass,其中有一个私有方法 privateMethod: public class ExampleClass {private void privateMethod(String message) {System.out.println("Private method called with message: " + message);} }我们可以使用上述代码来调用这个…...
你知道这些鼎鼎大名的Java底层核心公司吗
在讨论Java虚拟机——JVM的时候,有几个知名的,不得不提到的JVM的产品和公司。 一、Oracle HotSpot:这是由Sun公司开发的虚拟机。它由最初的Classic VM开始,到推出崭露头角的Exact VM的虚拟机,是现代化高性能虚拟机的最…...

C++入门级文章
一、一个用于查询C标准库内函数、操作符等的链接 https://legacy.cplusplus.com/reference/ 声明:该文档并非官方文档,但其具有易于查询和使用的优势,足够日常使用。 二、C的第一个程序 1、C语言中的语法在C中仍旧适用,首先我们来…...

modelsim仿真quartus IP
开发环境:quartus prime pro 20;modelsim se-64 10.6d 1. 生成Altera的IP库 使用quartus生成IP库,需要使用Simulation Library Compiler(Tools->Launch Simulation Library Compiler) 如下图操作,选择…...

PCB设计经验——布线原则
1.连线精简——避免直角布线 导线也应看作一种元器件,有自己的电阻,电感,电容 PCB走线在直角转弯的地方,信号前后部分相互影响,导致分布电容增加,对信号上升沿和下降沿有延缓影响。从阻抗的角度来说&#…...

C++进阶:设计模式___适配器模式
前言 在C的基础语法的学习后,更进一步为应用场景多写代码.其中设计模式是有较大应用空间. 引入 原本在写容器中适配器类有关的帖子,发现适配模式需要先了解,于是试着先写篇和适配器模式相关的帖子 理解什么是适配器类,需要知道什么是适配器模式.适配器模式是设计模式的一种.笔…...

“八股文“在现代编程面试中的角色重塑:助力、阻力还是桥梁?
🌈所属专栏:【其它】✨作者主页: Mr.Zwq✔️个人简介:一个正在努力学技术的Python领域创作者,擅长爬虫,逆向,全栈方向,专注基础和实战分享,欢迎咨询! 您的点…...
Android 安装应用-浏览阶段
应用安装的浏览阶段主要是由PackageManagerService类中的scanPackageNewLI()实现的,看一下它的代码: // TODO: scanPackageNewLI() and scanPackageOnly() should be merged. But, first, commiting// the results / removing app data needs to be move…...

JavaEE 初阶(10)——多线程8之“单例模式”
目录 一. 设计模式 二. 单例模式 2.1 饿汉模式 2.2 懒汉模式 a. 加锁synchronized b. 双重if判定 c. volatile关键字(双重检查锁定) 一. 设计模式 设计模式是在软件工程中解决常见问题的经典解决方案。针对一些特定场景给出的一些比较好的解决…...
Javascript常见设计模式
JS设计模式学习【待吸收】-CSDN博客 JavaScript 中的设计模式是用来解决常见问题的最佳实践方案。这些模式有助于创建可重用、易于理解和维护的代码。下面列出了一些常见的 JavaScript 设计模式及其代码示例。 1. 单例模式(Singleton) 单例模式确保一…...

JavaFX布局-SplitPane
JavaFX布局-SplitPane 常用属性orientationpaddingdividerPositionsdisable 实现方式Java实现fxml实现 一个拆分至少两个区域的容器支持水平、垂直布局可以拖动区域的大小初始化大小通过比例设置[0,1] 常用属性 orientation 排列方式,Orientation.VERTICAL、Orien…...

2.MySQL库的操作
创建数据库 创建数据库的代码: CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [,create_specification] ...];create_specification:[DEFAULT] CHARACTER SET charset_name[DEFAULT] COLLATE collation_name 说明: 大写的表示关键…...
如何学习计算机
不要只盯着计算机语言学习,你现在已经学习了C语言和Java,暑假又规划学习Python,最后你掌握的就是计算机语言包而已。 2. 建议你找一门想要深挖的语言,沿着这个方向继续往后学习知识就行。计算机语言是学不完的,而未来就…...

Spring MVC 快速入门指南及实战演示
1、SpringMVC简介 1.1 背景 Servlet属于web层开发技术,技术特点: 1. 每个请求都需要创建一个Servlet进行处理 2. 创建Servlet存在重复操作 3. 代码灵活性低,开发效率低 是否有技术方案可以解决以上问题? 1.2 SpringMVC概述 Sp…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...

macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...