内存溢出与内存泄漏

一.内存泄漏

  内存泄漏指对象已经没有被应用程序使用,但是垃圾回收器无法移除它们,因为还在被引用着。

  出现内存泄漏的情况和防止长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。

  1.当将HashMap,ArrayList,Vector等集合定义为静态的时候,他们的声明周期将会和应用程序一样长。他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。静态变量是全局的,GC不会回收。

  2.事件监听器,当一个监听器在使用的时候被注册,但不再使用时被反注册,会出现内存泄漏。

  3.如果一个类自己管理内存,常一些成员变量引用其他对象,初始化的时候需要置空。

  4.JDK6中的substirng()方法容易导致内存泄漏。

  5.各种连接 :
  比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。

  解决方法:通过工具查看泄漏对象到GC Roots的引用链,就能找到泄露对象是怎样的路径与GC Roots相连并导致垃圾回收器无法自动回收。

二.内存溢出

  内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。

  出现内存溢出的情况:

  1.内村中加载的数量过大,如一次从数据库中取出多条数据:

  2.栈溢出:线程请求栈的深度大于虚拟机所允许的最大深度(即无限递归出现栈溢出)或虚拟机扩展栈时无法申请到足够的空间(创建过多的线程出现内存溢出)。

  3.堆溢出:不断地创建对象,并保证GC Root到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量达到最大堆的容量后就会产生内存溢出。

  解决方案:从代码上检查是否存在某些对象声明周期过程,持有状态的时间过长等,尝试减少程序中运行期的内存消耗。

原文地址:https://www.cnblogs.com/xyzyj/p/7745446.html