如何修复“JavaScript 堆内存不足错误”

JavaScript 因其广泛的应用性,仍然是使用最为广泛的编程语言之一。要在浏览器环境之外运行 JavaScript,开发者需要安装一个跨平台的运行时环境,即 Node.js。

在运行 JavaScript Node.js 项目时,JavaScript 堆内存不足错误是常见的问题。

当计算机系统分配的默认内存不足以支撑大型项目的运行时,就会发生 JavaScript 堆内存不足的问题。

如果遇到堆内存不足错误,程序将会崩溃,并显示以下输出:

致命错误:CALL_AND_RETRY_LAST 分配失败——JavaScript 堆内存不足

或者

致命错误:无效的表大小分配失败 – javascript 堆内存不足

JavaScript 堆内存不足错误的起因

  • 大型数据结构的存在:使用诸如矩阵或数组之类的大型数据结构会消耗大量的内存空间,最终导致堆内存不足的错误。

以下是一个包含十亿个元素的大型数据结构的例子:

let array = [];

for (let i = 0; i < 1000000000; i++) {

  array.push(i);

}
  • 糟糕的内存管理:随着应用程序的扩展,需要释放一些不再需要的对象。

以下是一个导致内存泄漏的函数示例:

let array = [];

setInterval(function() {

  array.push(new Array(1000000).join("x"));

}, 1000);
  • 无限循环:这样的代码会永远运行,因为它永远不会满足终止条件。

以下是一个永远执行的无限循环的例子:

while (true) {

    console.log(1);

}

无限循环会导致此错误,因为它会迅速消耗内存。

  • 递归函数:递归函数是一种直接或间接调用自身以重复执行一组指令的函数,直至满足特定条件。如果这些函数设计不当,很可能导致内存错误,最终造成堆内存溢出。
  • 一段代码中存在大量对象:如果代码中包含许多大型对象,它们共同占用的内存可能会超出限制。

修复 JS 堆内存不足错误

此错误可能会在 Windows、macOS 以及基于 Linux 的操作系统(如 Ubuntu)中发生。 幸运的是,无论使用何种操作系统,此错误都是可以修复的。

#1. 修复 Windows 操作系统上的 JavaScript 堆内存不足错误

第一步:点击开始菜单,搜索并打开“高级系统设置”。

第二步:在对话框的左下方,点击“环境变量”。

第三步:在“用户变量”或“系统变量”下,点击“新建”。第一个选项将更改应用于当前用户账户,而第二个选项将更改应用到整个系统。

第四步:在弹出的窗口中,“变量名”输入“NODE_OPTIONS”,“变量值”输入“–max-old-space-size=4096”。在这里,数字 4096 表示为 Node.js 分配 4GB 的虚拟内存。 可以通过将值设置为“–max-old-space-size=8192”来分配更多空间,例如 8GB。

第五步:点击“确定”、“应用”,最后点击“确定”以保存更改。

也可以使用 Windows PowerShell 终端来解决此错误。在 Windows 操作系统上打开终端,输入以下命令:

env:NODE_OPTIONS="--max-old-space-size=4096"

也可以在运行应用程序之前执行以下命令来临时解决此错误:

set NODE_OPTIONS=--max-old-space-size=4096

#2. 修复 Linux 上的 JavaScript 堆内存不足错误

  • 第一步:确定错误的来源。 检查控制台日志或输出,以确定导致错误的代码或文件行。
  • 第二步:导出一个环境变量,指定为 Node.js 分配的虚拟内存。使用以下命令:
export NODE_OPTIONS=--max-old-space-size=4096

这些步骤将为 Node.js 分配 4GB 的虚拟内存。 如果错误仍然存在,可以通过增加内存大小来解决,例如翻倍。

例如,如果想分配 8GB 作为虚拟内存,可以运行以下命令:

export NODE_OPTIONS=--max-old-space-size=8192

#3. 修复 macOS 上的 JavaScript 堆内存不足错误

可以使用与 Linux 中类似的方法来解决 macOS 中的 JavaScript 堆内存不足错误。 按照以下步骤:

  • 第一步:通过检查控制台日志或输出来确定错误的来源,以确定导致错误的代码或文件行。
  • 第二步:导出一个环境变量,指定为 Node.js 分配的虚拟内存。使用以下命令:
export NODE_OPTIONS=--max-old-space-size=4096

这些步骤将为 Node.js 分配 4GB 的虚拟内存。 如果错误仍然存在,可以通过增加内存大小来解决,例如翻倍。

例如,如果想分配 8GB 作为虚拟内存,可以运行以下命令:

export NODE_OPTIONS=--max-old-space-size=8192

在 NPM 安装期间增加内存

到目前为止,我们提供的解决方案适用于运行 Node.js 应用程序时发生的错误。 但是,在安装 JavaScript 包时也可以分配虚拟内存来解决堆内存不足错误。 使用以下命令:

node --max-old-space-size=4096 (which npm) install

注意:可以逐步增加虚拟内存的分配,例如 1GB、2GB、3GB 或 4GB。 必须以 MB 为单位指定内存大小。 然而,不要将机器的全部内存都分配给 Node.js,因为这可能会导致程序崩溃。 一个好的实践是,如果机器有 16GB 内存,最多可以分配 8GB 给 Node.js。

预防 JavaScript 堆溢出内存错误

目前为止,我们已经讨论了在发生 JavaScript 堆内存不足错误时如何修复它。 幸运的是,还可以采取措施来防止在运行 JavaScript 代码时发生此错误。 以下是一些最佳方法:

#1. 将数据分成小块

可能有一个 Node.js 程序,通过 ETL(提取 – 转换 – 加载)过程从大型 CSV 文件导入大型数据集。 当尝试导入数据时,可能会发现应用程序总是崩溃。 如果使用的是 MongoDB,可以使用命令行指令来解决错误,例如:

split -l 1000000 users.csv

此命令指示 Node.js 将名为 users 的文件拆分为多个文件,每个文件包含 1,000,000 个用户。 -l 标志指定应根据代码行数拆分文件。

#2. 监控内存使用情况

可以使用内存分析器来检测代码中的内存泄漏。 可以结合 Node.js 的内置内存和 ChromeDevTools 来实现此目的。 这两者都可以检测代码中的问题并修复它们。

还可以使用 Datadog、New Relic 和 AppDynamics 等外部工具来监控应用程序的性能并采取必要的措施。 可以通过 `process.memoryUsage()` 方法来检查 Node.js 应用程序的内存使用情况。

#3. 避免内存泄漏

当 Node.js 应用程序保留对不再需要的对象的引用时,就会发生内存泄漏。 如果这些对象没有被垃圾回收,内存使用量将随着时间的推移而增加。

有几种方法可以避免内存泄漏,例如避免在代码中使用全局变量,避免阻塞 I/O 操作,以及在声明变量时使用 `let` 和 `const` 关键字而不是 `var`。

#4. 衍生进程

如果在内存有限的机器上运行 Node.js,例如 Raspberry Pi,很可能会遇到内存不足的错误。 可以有一个主进程,而其他进程被分组为工作进程。 一旦主进程检测到系统内存不足,它会终止该进程并将任务分配给另一个没有超载的进程。

#5. 更新硬件

如果增加内存分配和执行所列的防止堆溢出内存错误的过程都不能解决问题,可以考虑更新硬件。 Node.js 可以在低至 512MB 的 RAM 上运行。 但是,随着应用程序的增长,将需要更多的内存。

另一方面,增加 CPU 的数量也可以改善内存分配。 理想情况下,两个或多个 CPU 将允许应用程序为 CPU 密集型任务(如加密和图像处理)使用工作线程。

常见问题

是什么导致 JavaScript 堆内存不足错误?

此错误可能由多种原因引起:
1. 内存泄漏
2. 无限循环
3. 项目中存在多个对象
4. 大型数据结构的存在

JavaScript 堆内存不足错误是否可以解决?

是的。 可以通过以下方法解决错误:
1. 为 Node.js 分配更多的虚拟内存
2. 消除内存泄漏
3. 优化代码
4. 升级硬件

如何解决 React 应用程序中的堆内存不足错误?

React 是最流行的 JavaScript 库之一。 在根目录中找到 `package.json` 文件,并在脚本部分添加以下行:

"scripts": {

    "start": "react-scripts --max_old_space_size=4096 start",

    "build": "react-scripts --max_old_space_size=4096 build",

    "test": "react-scripts test",

    "eject": "react-scripts eject"

}

总结

大多数开发人员在运行 Node.js 程序时习惯于遇到错误和代码错误,而不是运行时错误。幸运的是,不必为此担心,因为堆内存不足错误是可以修复的。我们已经定义了什么是 JavaScript 堆内存不足错误,解释了如何解决它,以及如何在接下来的 Node.js 项目中避免它。

接下来,还可以阅读如何避免一些常见的 JavaScript 错误。