内存溢出原因与解决方案(4大主流方案详解)
内存溢出(OOM)是线上经常面临的问题,也是大厂面试经常考察的内容,下面我就全面来详解内存溢出(OOM)的原因及解决方案@mikechen

内存溢出,简称OOM,内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
比如申请了一个integer, 但给它存了long才能存下的数,那就是内存溢出。
再比如:你的电脑只有16GB的内存,已经把这16GB的内存用完了,但是还在继续用,就会造成内存溢出。
- 启动参数内存值设定的过小
- 内存中加载的数据量过于庞大;
- 对象的引用使用完后未清空,使得 JVM 不能回收;
- 代码中存在死循环或循环产生过多重复的对象实体;
在不同的Web服务器或程序中,此错误常见的错误提示如下:
- tomcat: java.lang.OutOfMemoryError: PermGen space
- tomcat: java.lang.OutOfMemoryError: Java heap space
- weblogic: Root cause of ServletException java.lang.OutOfMemoryError
- resin: java.lang.OutOfMemoryError
- java: java.lang.OutOfMemoryError
这些都是属于典型的内存溢出,接下来我们看看具体的内存溢出的解决办法。
这里我就以Java举例,常见的Java内存溢出主要是以下三种方式:
这是很常见的一种内存溢出,报错信息如下:
举一个死循环的例子,源码如下:
这里会不断死循环list.add(new Obj()),不断的创建对象,当不总容量触及最大堆容量时,就会产生溢出,出现如下提示:
解决办法:
1、首先排查,检查是否存在大对象的分配,最有可能的是大对象分配。2、其次,再通过jmap命令,把堆内存dump下来,使用mat工具分析一下,检查是否存在内存泄露的问题。3、如果没有找到明显的内存泄露,可以适当调整-Xms和-Xmx两个JVM参数。
比如上面的例子,在第二个步骤通过dump下来的堆,用工具可以分析出死循环的位置,就可以及时解决堆溢出。
如果通过上面的两个步骤都排查后,没有发现问题,再调整JVM堆的初始化参数,问题基本就可以解决。
首先搞清楚java栈空间存储的是什么,栈内存可以分为虚拟机栈(VM Stack)和本地方法栈(Native Method Stack)。
每个方法执行时都会在java栈空间产生一个栈帧,存放方法的变量表,返回值等信息,方法的执行到结束就是一个栈帧入栈到出栈的过程。
具体来说,当线程执行某个方法时,JVM会创建栈帧并压栈,此时刚压栈的栈帧就成为了当前栈帧。
如果该方法进行递归调用时,JVM每次都会将保存了当前方法数据的栈帧压栈,每次栈帧中的数据都是对当前方法数据的一份拷贝,如果递归的次数足够多,多到栈中栈帧所使用的内存超出了栈内存的最大容量,此时JVM就会抛出StackOverflowError。
还是看一个例子:
最后就会出现:
总之,不论是因为栈帧太大还是栈内存太小,当新的栈帧内存无法被分配时,JVM就会抛出StackOverFlowError,通常栈内存可以通过设置-Xss参数来改变大小。
永久区(Perm) 存放了被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等。
在JDK 1.8中,永久区被一块称为元数据的区域替代, 但是它们的功能是类似的,都是为了保存类的元信息,如果一 一个系统定了太多的类型,那么永久区是有可能溢出的,报错信息如下:
解决方法有如下几种:
1、检查是否永久代空间或者元空间设置的过小
2、检查代码中是否存在大量的反射操作
3、dump之后通过mat检查是否存在大量由于反射生成的代理类
4、放大招,重启JVM
电脑OUT OF MEMORY怎么解决
如果你的电脑配置低,且内存不足,那么很有可能在使用中系统很可能终止你正在运行的任务,并弹出“OUT OF MEMORY”这样的提示。
在遇到“OUT OF MEMORY”,如何确定是否是内存不足呢?很简单,打开任务管理器查看“性能”即可。如果物理内存使用率接近100%,那么可能我们需要升级下电脑内存,增加内存容量。
今年开始,内存条的降价明显。前段时间内存条价格甚至 降到了2016至今的最低点。光威DDR4 8G 2400曾一度价格189。 许多玩家都已信仰入手,但是也有很多玩家当时仍在观望。然而随后美国对中国加关税,美元上涨等因素导致,内存条的价格又有所上涨。目前内存条的价格要比前不久稍微贵了一点。但是我们不得不担心618时内存条的价格到底会不会比现在还低。
目前,光威8G DDR4 2133¥199,这仍然是非常具有性价比的。如果大家需要内存条,那么大家可以入手这款。或者,等618吧。另外,如果你暂时不打算,增加内存容量,你可以通过提升虚拟内存的方法来暂时的缓解内存不足的状况。
首先,我们要看虚拟内存的使用情况。命令提示符输入 systeminfo,查看虚拟内存的使用情况。如果虚拟内存不足,可增大虚拟内存。
再打开“高级系统设置”“性能”“高级”更改“虚拟内存”,取消自动,选择“自定义大小”,进行更改。
一般情况下WIN10系统,默认的虚拟内存就够了,不用另行设定。虚拟内存设置大了也效果不大,毕竟不是物理内存。所以,还是建议大家如果内存不足,就增加下内存容量,毕竟现在内存条的价格已经便宜下来了。近期市场状况复杂,早买早享受,晚买未必有折扣。