内存溢出与内存泄漏
1. 内存溢出(Out Of Memory,OOM)
概念:
内存溢出是指程序在运行过程中,尝试申请的内存超过了系统所能提供的最大内存限制,并且垃圾收集器也无法提供更多的内存,导致程序无法正常运行。
原因:
- 程序分配的内存过大: 处理超大文件、加载大量数据等操作,可能会导致内存需求超过系统限制。
- 比如你申请了一个 Integer 的变量,但是给了它一个 Long 类型才能存下的数,那就是内存溢出
- 内存泄漏: 长期积累的内存泄漏,会逐步消耗系统内存,最终导致内存溢出。
- 系统内存不足: 系统本身的内存容量有限,当运行多个程序或大型程序时,可能会出现内存不足的情况。
2. 内存泄漏(Memory Leak)
概念:
内存泄漏是指程序在在申请内存后,无法释放已申请的内存空间,一次内存泄漏的危害可以忽略,但内存泄漏堆积后果会很严重,无论有多少内存,都迟早会被占光。
原因:
-
静态集合类引起的内存泄漏:
- 使用
HashMap
、Vector
等静态集合时,容易出现内存泄漏。这些静态变量的生命周期与应用程序一致,因此容器中的对象在程序结束之前将不能被释放。简单来说,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但由于长生命周期对象持有它的引用,导致不能被回收。 - 单例模式,一般单例的对象都会设置为静态的,单例的生命周期和应用程序一样长,所以单例程序中,如果持有对外部对象的引用的话(这个外部对象只在某一小段时间使用,生命周期本该很短),那么这个外部对象是不能被回收的,则会导致内存泄漏的产生
- 解决方法:静态引用时注意将应用对象置空或少用静态引用。
- 使用
-
资源未关闭或释放导致的内存泄漏:
- 在程序中创建或打开流、新建网络连接等时,JVM 会为这些资源分配内存做缓存。如果忘记关闭这些资源,会阻塞内存,导致垃圾回收无法进行清理。特别是当程序发生异常时,没有在
finally
中进行资源关闭的情况。 - 解决方法:在资源使用完毕后,务必在
finally
块中关闭资源。
- 在程序中创建或打开流、新建网络连接等时,JVM 会为这些资源分配内存做缓存。如果忘记关闭这些资源,会阻塞内存,导致垃圾回收无法进行清理。特别是当程序发生异常时,没有在
-
不正确的
equals()
和hashCode()
:- 在
HashMap
和HashSet
这种集合中,经常用到equals()
和hashCode()
来比较对象。如果重写不合理,会成为潜在的内存泄漏问题。 - 解决方法:重写
equals()
和hashCode()
方法,确保正确比较对象。¹²
- 在
3. 总结
- 内存溢出是指内存不够用,而内存泄漏是指内存被占用无法释放。
- 内存泄漏会导致内存溢出!!