内存溢出与内存泄漏

内存溢出(OOM)

在程序运行中,无法申请到足够的内存资源

虚拟机栈 本地方法栈 堆 方法区 都会产生OOM

内存溢出常见的原因有以下几种:

内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
代码中存在死循环或循环产生过多重复的对象实体;
集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
启动参数内存值设定的过小
解决方案
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数)
第二步,检查错误日志
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。
第四步,使用内存查看工具动态查看内存使用情况
其中第三步
检查对数据库查询中,是否有一次获得全部数据的查询

一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

检查代码中是否有死循环或递归调用重复产生新对象实体。

检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收

内存泄漏

不再被使用的对象占用的内存空间,本应该被释放,但没有被垃圾回收
分类:

经常发生:发生内存泄露的代码会被多次执行,每次执行,泄露一块内存;

偶然发生:在某些特定情况下才会发生;


一次性:发生内存泄露的方法只会执行一次;

隐式泄漏:一直占着内存不释放,直到执行结束;严格的说这个不算内存泄漏,因为最终释放掉了,但是如果执行时间特别长,也可能会导致内存耗尽。

产生原因

静态集合类、连接未关闭、作用域不合理、单例模式
使用静态的集合类。静态变量不会被垃圾回收,而集合占用的内存又一般很大

静态的,那么它们的生命周期与JVM程序一致,则容器中的对象在程序结束之前将不能被释放
长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

各种连接没有及时关闭,比如数据库连接、IO连接

变量的作用域设置不合理,存活周期过长。
一些强引用的对象,在不使用后没有置为null,导致无法被回收

过多的单例模式类

单例模式,和静态集合导致内存泄露的原因类似,因为单例的静态特性,它的生命周期和整个程序的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏

解决方案
少用静态集合、静态变量(静态变量的生命周期和类同步的)减少长生命周期的对象持有短生命周期的引用
及时关闭连接
及时释放无用的对象引用,对于不需要使用的对象手动设置null值

内存泄露与内存溢出的关系:

内存泄漏的堆积最终会导致内存溢出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值