JVM学习和分析(三):OOM

来源:互联网 发布:vk社交软件下载 编辑:程序博客网 时间:2024/06/07 11:10

一、关于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运行效率

   

 

原创粉丝点击