一、关于OOM
对于JAVA程序员来说,恐怕都到过OOM这个可怕的梦厣,写出一段经常出现OOM的代码,恐怕也是对于一个程序员最大的耻辱。OOM出现的原因多种多样,在我刚开始写程序的时候,天真的以为OOM真的只是内存不够了,后来才发现,那个时候真的很傻很天真
二、诱发OOM的原因
OOM的原因基本上是因为在JVM做过一次GC(可能是YGC也可能是FULL GC)后,仍有大量对象存活,导致内存在无法释放的前提下,不断的有新的对象产生,最终导致某一块区域的内存不够,从而抛出OOM
三、各种OOM
1、堆溢出
由堆溢出引发的OOM是最常见的一种,这种OOM多半是由于程序员在写代码时,对内存的乱用导致的
导致堆溢出的原因一般有两个:内存泄漏、内存溢出
内存泄漏:需要通过一些工具确定是哪部分内存泄漏,修复之即可解决
内存溢出:由于内存中的对象必须存活,而导致的内存不足,一般这类问题通过调整-Xmx和-Xms可以得到解决
异常中的相关提示:Java heap space
个人经验:
减少对象存活时间:尽量避免让对象进入S0,01和OLD区,在Eden区的对象都是可以被快速回收的,从而释放内存
减少对象数量:一个线程中尽量避免有大对象列表或是MAP,从而减少每个线程占用的内存空间
2、本地方法栈溢出
本方方法栈会有两个异常抛出:OutOfMemoryException和StackOverflowException
OutOfMemoryException:
JVM扩展内存时,无法申请到足够的内存,通过在多线程环境下会出现这种问题
原因:
JVM每创建一个线程就会为线程创建一份本地方法栈内存,当线程过多时,会导致内存不足
解决办法:
a、减少线程数量,使每个线程可以得到更多的内存
b、通过设置-Xss减少栈内存容量,使JVM可以创建更多的线程
StackOverflowException:
线程请求的栈深度超出JVM允许的最大深度
个人经验:
减少本地变量定义
可分配给栈使用的内存=每个进程可使用的最大内存(系统限制)-Xmx-MaxPermSize-JVM进程占用内存
3、方法区溢出
由于创建了大量的类,方法区内存被完全使用,无法再存储新对象实例的相关信息(类名,访问修改符,常量池等),从而导致OOM
个人经验:
控制对象数量,让对象快速被回收
4、本机直接内存溢出
本人没遇到过,似乎很少会有这种OOM
四、总结
避免OOM的本质是让对象尽可能多的只存活在Eden区,避免长时间持有对象,避免创建大量对象,提高GC运行效率