• Java内存溢出问题总结


    使用Java那么久,在此总结一下Java中常见的内存溢出问题以及对应的解决思路

    堆溢出

    报错信息

    java.lang.OutOfMemoryError: Java heap space
    

    报错原因

    • 堆中(新生代和老年代)无法继续分配对象了;
    • 某些对象的引用长期被持有没有被释放,垃圾回收器无法回收;
    • 使用了大量的 Finalizer 对象,这些对象并不在 GC 的回收周期内。

    解决办法

    • 将堆内存 dump 下来,使用 MAT 分析一下,解决内存泄漏;
    • 如果没有内存泄漏,使用 -Xmx 增大堆内存;
    • 如果有自定义的 Finalizable 对象,考虑其存在的必要性。

    GC超载溢出

    报错信息

    java.lang.OutOfMemoryError:GC overhead limit exceeded
    

    报错原因

    垃圾回收器超过98%的时间用来做垃圾回收,但回收了不到2%的堆内存。

    解决办法

    • 添加 -XX:-UseGCOverheadLimit 这个启动参数去掉报警,但这只是一种掩耳盗铃的方式,一般出现 GC overhead limit exceeded 说明离真正的 OOM 也不远了;
    • 将堆内存 dump 下来,使用 MAT 分析一下,解决内存泄漏;
    • 如果没有内存泄漏,使用 -Xmx 增大堆内存;

    永久代/元空间溢出

    报错信息

    java.lang.OutOfMemoryError: PermGen space 或者
    java.lang.OutOfMemoryError: Metaspace(Java8及以上)
    

    报错原因

    永久代是 HotSot 虚拟机对 方法区的具体实现,存放了已被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等。需要注意的是,在Java8后,永久代有了一个新名字:元空间,元空间使用的是本地内存。永久代里存在的信息也有了若干变化:

    • 字符串常量由永久代转移到堆中;
    • 和永久代相关的JVM参数已移除。

    出现永久代或元空间的溢出的原因可能有如下几种:

    • 有频繁的常量池操作(eg. String.intern),这种情况只适用于Java7之前应用;
    • 加载了大量的类信息,且没有及时卸载;
    • 应用部署完后没有重启。

    解决办法

    永久代/元空间 溢出的原因比较简单,解决方法有如下几种:

    • Java8前的应用:使用 -XX:MaxPermSize 增加永久代的大小();
    • Java8及以后的应用:如果设置了 -XX:MaxMetaSpaceSize,调整其大小或者移除掉该参数。
    • 尝试重启JVM。

    方法栈溢出

    报错信息

    java.lang.OutOfMemoryError : unable to create new native Thread
    

    报错原因

    虚拟机在拓展栈空间时,无法申请到足够的内存空间。一般出现在内存空间过小,但是又创建了大量的线程的场景。

    解决办法

    • 通过-Xss降低的每个线程栈大小的容量,注意-Xms,-Xmx的影响;
    • 线程总数也受到系统空闲内存和操作系统的限制,检查是否该系统下有此限制:
      • /proc/sys/kernel/pid_max,
      • /proc/sys/kernel/thread-max,
      • max_user_process(ulimit -u),
      • /proc/sys/vm/max_map_count

    数组分配溢出

    报错信息

    java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    

    这种情况一般是由于不合理的数组分配请求导致的,消除代码逻辑错误或者调整堆大小。

    Swap分区溢出

    报错信息

    java.lang.OutOfMemoryError: Out of swap space
    

    这种情况一般是操作系统导致的,可能的原因有:

    • swap 分区大小分配不足;
    • 机器上其他进程消耗了所有的内存。

    本地方法溢出

    报错信息

    java.lang.OutOfMemoryError: stack_trace_with_native_method
    

    这种情况表明,本地方法在运行时出现了内存分配失败。和java.lang.OutOfMemoryError : unable to create new native Thread 保存不同,方法栈溢出出现在 JVM 的代码层面,而本地方法溢出发生在JNI代码或本地方法处。

  • 相关阅读:
    图论
    后缀数组专题
    AC自动机
    线段树·二
    nginx实现负载均衡
    关于mysql binlog二进制
    linux下每次git clone无需多次输入账号密码
    Centos7 yum安装 MySQL5.7.25
    docker基本操作和部署
    composer update 或者 composer install提示killed解决办法
  • 原文地址:https://www.cnblogs.com/senlinyang/p/8717933.html
Copyright © 2020-2023  润新知