内存溢出是“要不到”,内存泄漏是“还不掉”;前者因申请时可用内存不足当场抛OutOfMemoryError,后者因强引用残留致垃圾回收无法释放内存,长期积累终致溢出。

内存溢出(OOM)和内存泄漏(Memory Leak)本质不同:前者是“要不到”,后者是“还不掉”。
内存溢出:申请失败,当场报错
程序明确要求一块内存(比如新建一个大数组、加载一个超大文件),但系统当前可用内存(如JVM堆上限、物理内存、直接内存等)已不足以满足这次分配请求,于是立刻抛出 OutOfMemoryError。它不关心之前内存用得是否合理,只看“此刻能不能给”。
- 可能是一次性操作引发的,比如循环读取10GB日志进内存
- 也可能由配置不当导致,例如 -Xmx 设置为64M,但业务正常峰值需512M
- 不限于堆内存:栈溢出(StackOverflowError)、元空间溢出(Metaspace)、直接内存溢出都属于OOM范畴
内存泄漏:引用残留,悄悄囤积
对象本该被回收(程序逻辑上已不再使用),但由于某些强引用仍存在(如静态集合、未注销监听器、ThreadLocal未清理),导致垃圾回收器无法将其标记为可回收——这块内存“卡住”了,既不能被程序再用,也不能被系统复用。单次泄漏影响微小,但随时间推移,占用持续增长。
- 典型表现是老年代内存使用量缓慢但稳定上升,Full GC 后也降不下来
- 常见源头包括:static Map 缓存未设上限、流/连接未 close、内部类隐式持外部引用、监听器注册后忘记 remove
- 泄漏本身不会立即崩溃,但它是 OOM 最常见的长期诱因
关键区别一句话总结
内存泄漏是资源归还环节出问题(该释放没释放),内存溢出是资源申请环节出问题(要得太多或剩得太少)。 泄漏是慢性病,溢出是急性发作;泄漏不一定立刻导致溢出,但溢出常常是泄漏积累到临界点的结果。










