溢出是“要不到”,泄漏是“该收没收”:溢出表现为明确报错(如outofmemoryerror)、瞬间崩溃;泄漏表现为内存缓慢增长、gc频繁但不回落、越用越卡。

面试时问“如何区分内存溢出与内存泄漏”,核心不是背定义,而是能说清现象、定位动作和修复逻辑。关键一句话:溢出是“要不到”,泄漏是“该收没收”。
看表现:崩溃还是缓慢卡顿
内存溢出一定伴随明确报错,比如 Java 的 OutOfMemoryError、前端的 RangeError: Maximum call stack size exceeded 或浏览器直接无响应;而内存泄漏不会立刻崩,但你会观察到:页面越用越慢、GC 频繁但内存曲线持续上扬、重启后暂时恢复——这是典型的“慢性消耗”。
查根源:一次申请失败 vs 长期引用残留
溢出往往由单次操作触发,例如:
- 一次性加载 500MB JSON 文件到内存
- 递归调用深度超过栈限制
- JVM 堆参数 -Xmx 设置过小(比如只配了 512MB 却跑大数据报表)
泄漏则源于代码中“不该留的引用一直留着”,常见有:
- 全局变量或静态集合(如 static Map)不断 put 对象却不清理
- 组件卸载后,定时器、事件监听器、第三方 SDK 回调没注销
- DOM 节点已移除,JS 还持有着它的引用(let node = document.getElementById(...))
用工具:快照对比比单纯看内存图更准
别只盯着 Memory 面板的实时曲线——它容易误判。正确做法是:
- 在 Chrome DevTools → Memory 标签,先拍 Snapshot 1(空闲状态)
- 执行疑似问题操作(如打开/关闭弹窗 3 次)
- 再拍 Snapshot 2,切换 Comparison 视图
- 筛选 Objects allocated between Snapshot 1 and Snapshot 2,重点看数量暴涨的构造函数(如 MyComponent、Array、LargeDataItem)
如果某类对象每次操作都新增且不回收,基本就是泄漏点。
定因果:溢出未必是泄漏,但泄漏迟早引发溢出
要避免“看到 OOM 就猛加内存”的误区。真正要判断的是:
- 如果是首次运行大任务就崩 → 很可能是配置不足或单次申请过大(溢出独立发生)
- 如果是运行几小时后才崩,且内存使用呈阶梯式上升 → 泄漏概率极高
- 线上日志里反复出现 GC 日志(如 “GC overhead limit exceeded”)→ 典型泄漏后期信号
修复方向也不同:溢出优先调参或优化单次负载;泄漏必须找到强引用链并切断。











