内存泄漏是“该收没收”,表现为无报错但内存阶梯式上升;内存溢出是“要不到”,表现为直接崩溃并报outofmemoryerror等错误。

面试中问“如何区分内存泄漏与内存溢出”,不是考定义背诵,而是看你能不能快速判断问题性质、定位根因、给出对应动作。核心就一句话:泄漏是“该收没收”,溢出是“要不到”——前者拖时间,后者直接撞墙。
看现象:崩溃与否 + 内存曲线走势
这是最直观的区分入口:
-
内存溢出:程序突然中断,控制台明确报错,如
OutOfMemoryError(Java)、RangeError: Maximum call stack size exceeded(JS)、或系统弹窗提示“内存不足”。过程往往是一次性操作后立刻发生,比如点击导入10万行Excel、递归渲染深层树结构。 - 内存泄漏:没有报错,但页面越来越卡、响应变慢、反复操作同一功能后内存占用持续攀升(DevTools → Memory → Chart 可见阶梯式上升)。重启页面能暂时恢复,但过一阵又回到高位。
查根源:关注对象生命周期是否失控
泄漏的本质是“本该回收的对象还被强引用着”,溢出的本质是“当前没空间满足新申请”:
- 泄漏常见源头:全局变量挂载(
window.data = bigArray)、定时器未清除(setInterval没clearInterval)、事件监听器未解绑(addEventListener后没removeEventListener)、DOM 节点被 JS 变量持有、闭包意外保留大对象、第三方 SDK 回调未注销。 - 溢出常见源头:一次性加载超大文件或数据(如
JSON.parse(hugeString))、JVM 堆配置过小(-Xmx512m却跑大数据任务)、死循环创建对象、栈深度超限(如无终止条件的递归)、线程数爆炸导致堆外内存耗尽。
用工具:快照比对 vs 实时分配追踪
别靠猜,用 Chrome DevTools 直观验证:
- 怀疑泄漏:先拍 Heap Snapshot 1(空闲状态)→ 执行可疑操作(如打开/关闭模块3次)→ 再拍 Snapshot 2 → 切 Comparison 视图 → 筛选 Objects allocated between Snapshot 1 and Snapshot 2 → 重点关注
Array、Object、自定义类实例数量是否异常增长。 - 怀疑溢出:打开 Memory → Record Allocation Timeline → 操作触发崩溃前流程 → 停止后看蓝色柱状图是否出现陡峭峰值且无法回落,尤其注意峰值附近分配了什么类型对象(比如全是
String或Uint8Array)。
定策略:修复方向完全不同
诊断清楚后,动作不能反:
- 确认是泄漏:重点做“减法”——清理引用链。删掉全局变量、补上
clearInterval/removeEventListener、用弱引用(WeakMap)缓存、组件卸载时手动释放资源、检查闭包是否无意捕获了大对象。 - 确认是溢出:先做“加法保命”,再做“优化治本”。比如临时调大 JVM
-Xmx、前端限制单次加载条数、用流式解析代替全量加载;长期则重构逻辑,分页/懒加载/对象复用/减少深层嵌套。
不复杂但容易忽略:泄漏不会立刻崩,但会悄悄把溢出变成早晚的事;溢出可能一次就发生,未必有泄漏。判断准了,排查效率翻倍。











