栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

常见OOM异常及原因

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

常见OOM异常及原因

1.堆内存溢出(Java heap space)

异常信息:java.lang.OutOfMemoryError: Java heap space
可能原因:死循环、递归层数太多、内存泄露。或者系统并发高请求量大内存太小。
解决方案:

  • 排查代码 jstack jmap jstat
  • 参数设置:-Xms1024m JVM启动内存初始大小 -Xmx3062m JVM启动内存的最大值
2.栈溢出(Thread Stack space)

异常信息:java.lang.StackOverflowError: Thread Stack space
可能原因:单线程调用方法次数太多,一般递归层数太多
解决方案:

  • 排查代码
  • 参数设置:-Xss512k 设置虚拟机栈大小
3.元空间不足(metaSpace)

**异常信息:**java.lang.OutOfMemoryError: metaSpace
**发生原因:**元空间不足
**解决方案:**增大元空间大小,配置参数-XX:MaxmetaspaceSize=xx

示例:
可在启动时配置的小一点,可模拟次异常, 比如设置 -XX:MaxmetaspaceSize=2m

注:

  • 元空间初始大小 默认21M
  • -XX:MaxmetaspaceSize=512m , 元空间最大可分配大小(一台机器多个服务可配置上限防止影响其他服务)
  • 也可能是代码问题,cglib动态代理生成的类过多塞满metaspace导致溢出。
4.GC效率太低(GC overhead limit exceeded)

异常信息:java.lang.OutOfMemoryError: GC overhead limit exceeded
发生原因:

  • 垃圾收集器GC效率很低,jvm花费超过 98%的 CPU 时间来进行一次 GC,
  • 但是回收的内存却少于 2%的堆空间大小,并且GC连续超过5次都这样

示例代码

public class GcOverrhead {
    public static void main(String[] args){
        Map map = System.getProperties();
        Random r = new Random();
        while (true) {
            map.put(r.nextInt(), "value");
        }
    }
}

启动时加参数:-Xmx45m -XX:+UseParallelGC -XX:+PrintGCDetails运行一段时间,就会出现以下异常。
可通过增加参数-XX:-UseGCOverheadLimit可以避免这个异常,但其实是治标不治本,还需实际定位修改代码问题。

5.数组大小超过限制(VM limit)

**异常信息:**java.lang.OutOfMemoryError: Requested array size exceeds VM limit
发生原因:

  • 请求分配的数组太大,导致jvm空间不足
  • 请求的数组大于等于Integer.MAX_INT - 1

示例代码1 :直接抛出Requested array size exceeds VM limit

int[] arr = new int[Integer.MAX_VALUE - 1];

示例代码2 :先抛出 Java heap space后再抛出Requested array size exceeds VM limit

for (int i = 3; i >= 0; i--) {
    try {
        int[] arr = new int[Integer.MAX_VALUE-i];
        System.out.format("Successfully initialized an array with %,d elements.n", Integer.MAX_VALUE-i);
    } catch (Throwable t) {
        t.printStackTrace();
    }
}
6.创建线程失败(Unable to create threads)

异常信息:java.lang.OutOfMemoryError: Unable to create native threads
可能原因:

  • 内存空间不够,jvm启动时参数-Xss指定每个线程占用的堆栈大小,如果内存不够,就会创建线程失败

  • 操作系统上ulimit中max user processes参数限制,这个参数指操作系统可以创建的全局线程数量

    • 可使用 ulimit -a | grep 'max user processes’命令可以查看,如下图
  • 参数sys.kernel.threads-max限制,

    • 可通过命令cat /proc/sys/kernel/threads-max来查看,如下图

    • 修改这个参数,需要在/etc/sysctl.conf文件,加入sys.kernel.threads-max = 10000

  • 参数sys.kernel.pid_max限制,这个参数只是每创建一个线程,都需要分配一个pid,当pid的值大于这个值时,就会创建失败。

    • 查看命令:cat /proc/sys/kernel/pid_max

    • 修改这个参数,需要在/etc/sysctl.conf文件,加入sys.kernel.pid_max =10000

7.堆外内存溢出(Direct buffer memory)

异常信息:nio handle failed java.lang.OutOfMemoryError: Direct buffer memory
可能原因:堆外内存不足
解决方案:

  • JVM参数设置最大堆外内存:-XX:MaxDirectMemorySize
  • 申请堆外内存代码:
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);//申请堆外内存1k

1、如果堆外内存足够,就直接预留一部分内存
2、如果堆外内存不足,则将已经被 JVM 垃圾回收的 DirectBuffer 对象的堆外内存释放
3、如果进行一次堆外内存资源回收后,还不够进行本次堆外内存分配的话,则进行 System.gc()
4、如果 9 次尝试后依旧没有足够的可用堆外内存,则抛异常
原因可能是年轻代设置太小,并且关闭了系统gc调用(-XX:DisableExplicitGC)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/581869.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号