当前位置: 首页 > news >正文

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…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

EtherNet/IP转DeviceNet协议网关详解

一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

React核心概念:State是什么?如何用useState管理组件自己的数据?

系列回顾&#xff1a; 在上一篇《React入门第一步》中&#xff0c;我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目&#xff0c;并修改了App.jsx组件&#xff0c;让页面显示出我们想要的文字。但是&#xff0c;那个页面是“死”的&#xff0c;它只是静态…...

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…...

【QT控件】显示类控件

目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏&#xff1a;QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…...

职坐标物联网全栈开发全流程解析

物联网全栈开发涵盖从物理设备到上层应用的完整技术链路&#xff0c;其核心流程可归纳为四大模块&#xff1a;感知层数据采集、网络层协议交互、平台层资源管理及应用层功能实现。每个模块的技术选型与实现方式直接影响系统性能与扩展性&#xff0c;例如传感器选型需平衡精度与…...