关于java:内存泄露与内存溢出的区别

36次阅读

共计 1688 个字符,预计需要花费 5 分钟才能阅读完成。

概念与区别

1、内存透露(memory leak) :

是指程序在 申请内存后,无奈开释已申请的内存空间,一次内存透露仿佛不会有大的影响,但内存透露沉积后的结果就是内存溢出。

2、内存溢出 (out of memory) :

指程序申请内存时,没有足够的内存供申请者应用,或者说,给了你一块存储 int 类型数据的存储空间,然而你却存储 long 类型的数据,那么后果就是内存不够用,此时就会报错 OOM, 即所谓的内存溢出。

3、二者的关系

内存透露的沉积最终会导致内存溢出内存溢出
就是你要的内存空间超过了零碎理论调配给你的空间,此时零碎相当于没法满足你的需要,就会报内存溢出的谬误。

  • 内存透露 是指你向零碎申请分配内存进行应用(new),可是应用完了当前却不偿还(delete),后果你申请到的那块内存你本人也不能再拜访(兴许你把它的地址给弄丢了),而零碎也不能再次将它调配给须要的程序。就相当于你租了个带钥匙的柜子,你存完货色之后把柜子锁上之后,把钥匙丢了或者没有将钥匙还回去,那么后果就是这个柜子将无奈供应任何人应用,也无奈被垃圾回收器回收,因为找不到他的任何信息。
  • 内存溢出 :一个盘子用尽各种办法只能装 4 个果子,你装了 5 个,后果掉倒地上不能吃了。这就是溢出。比方说栈, 栈满时再做进栈必然产生空间溢出,叫上溢 栈空时再做退栈也产生空间溢出,称为下溢。就是调配的内存不足以放下数据项序列, 称为内存溢出。说白了就是我接受不了那么多,那我就报错。

4、内存透露的分类(按产生形式来分类)

  • 常发性内存透露 :
    产生内存透露的代码会被屡次执行到,每次被执行的时候都会导致一块内存透露。
  • 偶发性内存透露 :
    产生内存透露的代码只有在某些特定环境或操作过程下才会产生。常发性和偶发性是绝对的。对于特定的环境,偶发性的兴许就变成了常发性的。所以测试环境和测试方法对检测内存透露至关重要。
  • 一次性内存透露 :
    产生内存透露的代码只会被执行一次,或者因为算法上的缺点,导致总会有一块仅且一块内存产生透露。比方,在类的构造函数中分配内存,在析构函数中却没有开释该内存,所以内存透露只会产生一次。
  • 隐式内存透露 :
    程序在运行过程中不停的分配内存,然而直到完结的时候才开释内存。严格的说这里并没有产生内存透露,因为最终程序开释了所有申请的内存。然而对于一个服务器程序,须要运行几天,几周甚至几个月,不及时开释内存也可能导致最终耗尽零碎的所有内存。所以,咱们称这类内存透露为隐式内存透露。

5、内存溢出的起因及解决办法:

A. 内存溢出起因:

1. 内存中加载的数据量过于宏大,如一次从数据库取出过多数据;2. 汇合类中有对对象的援用,应用完后未清空,使得 JVM 不能回收;3. 代码中存在死循环或循环产生过多反复的对象实体;4. 应用的第三方软件中的 BUG;5. 启动参数内存值设定的过小

B. 内存溢出的解决方案:

第一步,批改 JVM 启动参数,间接减少内存。(-Xms,-Xmx 参数肯定不要遗记加。)

第二步,查看谬误日志,查看“OutOfMemory”谬误前是否有其 它异样或谬误。

第三步,对代码进行走查和剖析,找出可能产生内存溢出的地位。
重点排查以下几点:

  • 1. 查看对数据库查问中,是否有一次取得全副数据的查问。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比拟荫蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查问就有可能引起内存溢出。因而对于数据库查问尽量采纳分页的形式查问。
  • 2. 查看代码中是否有死循环或递归调用。
  • 3. 查看是否有大循环反复产生新对象实体。
  • 4. 查看对数据库查问中,是否有一次取得全副数据的查问。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比拟荫蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查问就有可能引起内存溢出。因而对于数据库查问尽量采纳分页的形式查问。
  • 5. 查看 List、MAP 等汇合对象是否有应用完后,未革除的问题。List、MAP 等汇合对象会始终存有对对象的援用,使得这些对象不能被 GC 回收。

C. 第四步,应用内存查看工具动静查看内存应用状况(jvisualvm)

正文完
 0