内存泄漏(Memory Leak)和内存溢出(Out Of Memory,OOM)不是同一个概念,但两者存在密切关联,具体区别和联系如下:
1. 内存泄漏(Memory Leak)
指程序中不再使用的对象无法被垃圾回收器(GC)回收,导致这些对象持续占用内存空间的现象。
- 本质:"该释放的内存没释放",内存占用逐渐累积,但此时总内存可能还未耗尽。
- 特点:是一个 "慢性过程",内存占用会随时间推移逐渐增加(比如每次操作都泄漏一点内存)。
- 例子 :静态集合中缓存了大量无用数据且未清理、
ThreadLocal
未调用remove()
导致线程长期持有对象引用等。
2. 内存溢出(OOM)
指程序需要分配的内存超过了 JVM 所能提供的最大内存限制 ,导致无法继续分配内存的错误(抛出 OutOfMemoryError
)。
- 本质:"内存不够用了",此时内存已被耗尽(或接近耗尽)。
- 特点:是一个 "急性结果",通常在某一时刻突然发生(比如瞬间创建大量对象,超过内存上限)。
- 例子 :一次性加载海量数据到内存(如读取超大文件到
List
)、递归调用导致栈内存耗尽(StackOverflowError
是 OOM 的一种特殊情况)等。
3. 两者的关联
内存泄漏是导致内存溢出的常见原因之一:
- 长期的内存泄漏会使未回收的对象越来越多,逐渐耗尽 JVM 的可用内存,最终触发内存溢出。
- 但内存溢出不一定都是内存泄漏导致的,也可能是程序本身需要的内存超过了 JVM 的配置上限(比如正常业务逻辑需要加载大量数据,但内存配置不足)。
总结
- 内存泄漏:"内存没被正确释放,越用越多"(过程)。
- 内存溢出:"内存不够用了,无法分配新内存"(结果)。
- 内存泄漏可能最终导致内存溢出,但内存溢出的原因不止内存泄漏。
内存泄漏(Memory Leak)指的是程序中已不再使用的对象,由于某种原因未能被垃圾回收器(GC)正确回收,导致这些对象持续占用内存空间,最终可能引发内存溢出(OOM) 的现象。
简单说,就是 "该回收的对象没被回收,白白占着内存"。
常见原因:
- 长生命周期的对象持有短生命周期对象的引用(如静态集合缓存了不再使用的对象);
- 未关闭资源(如数据库连接、文件流未关闭,导致底层资源无法释放);
- 匿名内部类 /lambda 表达式意外持有外部类引用,导致外部类无法回收;
- ThreadLocal 未及时 remove (),导致线程池核心线程长期持有对象引用等。
二、Java 中所有的对象都有 close
属性吗?
不是。
close
通常是用于释放资源的方法(如关闭文件、网络连接、数据库连接等),但它并非 Java 中所有对象的 "标配":
- 只有实现了
AutoCloseable
或Closeable
接口的类,才会有close()
方法(这两个接口是 Java 用于规范资源释放的标准)。例如:FileInputStream
、Connection
(数据库连接)、Socket
等 "需要手动释放资源" 的对象,都实现了这些接口,因此有close()
方法。 - 普通对象(如
String
、List
、自定义 POJO 类等)不需要手动释放内存(由 GC 自动管理),因此没有close()
方法。
总结
- 内存泄漏是 "无用对象未被回收,占用内存" 的问题,本质是内存管理不当。
close()
方法仅存在于需要手动释放资源的对象中(如实现AutoCloseable
接口的类),并非所有 Java 对象都有。普通对象的内存由 GC 自动回收,无需close
。