内存泄漏与内存溢出

一、基本概念

1. 内存泄漏

内存泄漏是指那些本应该回收的内存对象无法被系统回收的现象。在 C++ 中需要手动释放内存对象,所以 C++ 中更容易出现内存泄漏。Java 引入了内存回收机制,使得在 C++ 中令人头疼的问题得到了改善,但并不意味着不需要关注 Java 中的内存,因为垃圾回收机制不能完全保证内存对象在该释放的地方释放,JVM 中普遍根据引用可达法性是否需要回收对象,可能会存在无用对象被游有用对象引用着,导致对象引用一直可达,垃圾回收器不敢冒然回收,从而造成内存泄漏。

2. 内存溢出

系统在为某段执行指令(程序)分配内存时,发现内存不足,抛出错误(Out of Memory)。

3. 关系

内存空间是有限的,为每个程序分配的空间更是有限的,当内存泄漏的对象越来越多,可调配的内存空间就约少,当可掉配的内存空间不够创建新对象时就会引起 OOM。

  • 相同点:都会导致应用程序运行出现问题,性能下降或挂起。
  • 不同点:内存泄露是导致内存溢出的原因之一,内存泄露积累起来将导致内存溢出;内存泄露可以通过完善代码来避免,内存溢出可以通过调整配置来减少发生频率,但无法彻底避免。

二、如何避免内存泄漏、溢出?

  1. 尽早释放无用对象的引用。让引用变量在退出活动域后自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。

  2. 程序进行字符串处理时,尽量避免使用 String,而应使用 StringBuffer。

  3. 尽量少用静态变量。因为静态变量是全局的,GC 不会回收。

  4. 避免集中创建对象尤其是大对象,如果可以的话尽量使用流操作。

  5. 尽量运用对象池技术以提高系统性能。生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。

  6. 不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。可以适当的使用 Hashtable 创建一组对象容器,然后从容器中去取那些对象,而不用每次 New 之后又丢弃。

  7. 优化配置。

参考