Java中常见OOM的场景及解决方法

一、OOM for Heap (java.lang.OutOfMemoryError: Java heap space) 分析

    此OOM是由于JVM中heap的最大值大于程序运行期间最大可用内存大小,如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。

  • 解决思路
  • 将设置heap的最大值调高即可,即-Xmx的值调大。参数样例为:-Xmx2G。

二、OOM for StackOverflowError (Exception in thread “main” java.lang.StackOverflowError)

  1. 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
  2. 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。
  • 解决思路
  • 检查程序是否有深度递归,或者根据-Xss 是指设定每个线程的堆栈大小。

三、OOM for Perm (java.lang.OutOfMemoryError: PermGen space)

    PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中。
    由于JVM在默认的情况下,Perm默认为64M,而很多程序需要大量的Perm区内 存,尤其使用到像Spring等框架的时候,由于需要使用到动态生成类,而这些类不能被GC自动释放,所以导致OutOfMemoryError: PermGen space异常。

  • 解决思路
  • 增大JVM的 -XX:MaxPermSize 启动参数,就可以解决这个问题。

四、OOM for GC (java.lang.OutOfMemoryError: GC overhead limit exceeded)

    此OOM是由于JVM在GC时,对象过多,导致内存溢出,建议调整GC的策略,在一定比例下开始GC而不要使用默认的策略,或者将新代和老代设置合适的大小。

  • 解决思路
  • 改变GC策略,在老代80%时就是开始GC,并且将-XX:SurvivorRatio(默认-XX:SurvivorRatio=8,定义了新生代中Eden区域和Survivor区域的比例)和-XX:NewRatio(默认-XX:NewRatio=4,定义了新生代和老年代的比例)设置的更合理。

五、OOM for native thread created (java.lang.OutOfMemoryError: unable to create new native thread)

    这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。

  • 解决思路
  • 如果JVM内存调的过大或者可利用率小于20%,可以建议将heap及perm的最大值下调,并将线程栈调小,即-Xss调小,如:-Xss128k。

六、OOM for allocate huge array (Exception in thread “main”: java.lang.OutOfMemoryError: Requested array size exceeds VM limit)

    此类信息表明应用程序试图分配一个大于堆大小的数组。例如,如果应用程序new一个数组对象,大小为512M,但是最大堆大小为256M,因此OutOfMemoryError会抛出,因为数组的大小超过虚拟机的限制。

  • 解决思路
  • 首先检查heap的-Xmx是不是设置的过小,如果太小就调大。
  • 如果heap的-Xmx已经足够大,那么请检查应用程序是不是存在bug,例如:应用程序可能在计算数组的大小时,存在算法错误,导致数组的size很大,从而导致巨大的数组被分配。

七、OOM for small swap (Exception in thread “main”: java.lang.OutOfMemoryError: request bytes for . Out of swap space? )

    抛出这类错误,是由于从native堆中分配内存失败,并且堆内存可能接近耗尽。

  • 解决思路
  • 检查是否有其他进程在消耗大量的内存,从而导致当前的JVM内存不够分配。

八、OOM for exhausted native memory (java.lang.OutOfMemoryErr java.io.FileInputStream.readBytes(Native Method))

    需要考虑问题的发生是由于Native memory被耗尽导致的。

  • 解决思路
  • 从根本上来说,解决此问题的方法应该通过检测发生问题时的环境下,native memory为什么被占用或者说为什么native memory越来越小,从而去解决引起Native memory减小的问题。
发布了185 篇原创文章 · 获赞 457 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_42146366/article/details/105126377