OOM内存溢出的原因和解决方法

一 堆溢出
  • java.lang.OutOfMemoryError: ......java heap space.....
    原因:要么代码有问题,要么访问量太多并且每个访问的时间太长或者数据太多,导致数据释放不掉,因为垃圾回收器是要找到那些是垃圾才能回收,这里它不会认为这些东西是垃圾,自然不会去回收。在这个溢出之前,可能系统会提前先报错关键字为 java.lang.OutOfMemoryError:GC over head limit exceeded。这种情况是当系统处于高频的GC状态,而且回收的效果依然不佳的情况,就会开始报这个错误,这种情况一般是产生了很多不可以被释放的对象,有可能是引用使用不当导致,或申请大对象导致,但是java heap space的内存溢出有可能提前不会报这个错误,也就是可能内存就直接不够导致,而不是高频GC。
    解决:此时如果代码没有问题的情况下,适当调整-Xmx和-Xms是可以避免的。

    -Xmx:最大堆
    -Xms:最小堆(初始值)

二 PermGen

Permanent Generation永久代的溢出

  • java.lang.OutOfMemoryError: PermGen space
    原因:系统的代码非常多或引用的第三方包非常多、或代码中使用了大量的常量、或通过intern注入常量、或者通过动态代码加载等方法,导致常量池的膨胀。
    解决:在面对这种情况常用的手段是:增加-XX:PermSize和-XX:MaxPermSize的大小。

    -XX:PermSize和-XX:MaxPermSize:永久代(元空间)size

三 ByteBuffer
  • java.lang.OutOfMemoryError: Direct buffer memory
    原因:在使用ByteBuffer中的allocateDirect()的时候会用到,如果你在直接或间接使用了ByteBuffer中的allocateDirect方法的时候,而不做clear的时候就会出现类似的问题,常规的引用程序IO输出存在一个内核态与用户态的转换过程,也就是对应直接内存与非直接内存,如果常规的应用程序你要将一个文件的内容输出到客户端需要通过OS的直接内存转换拷贝到程序的非直接内存(也就是heap中),然后再输出到直接内存由操作系统发送出去,而直接内存就是由OS和应用程序共同管理的,而非直接内存可以直接由应用程序自己控制的内存,jvm垃圾回收不会回收掉直接内存这部分的内存。
    解决:可以设置-XX:MaxDirectMemorySize

    -XX:MaxDirectMemorySize:最大直接内存size

四 栈溢出
  • java.lang.StackOverflowError
    原因:申请很多局部调用的栈帧等内容是存放在用户当前所持有的线程中的,线程在jdk 1.4以前默认是256K,1.5以后是1M,如果报这个错,只能说明-Xss设置得太小。(当然有些厂商的JVM不是这个参数,本文仅仅针对Hotspot VM而已;不过在有必要的情况下可以对系统做一些优化,使得-Xss的值是可用的。)
    解决:调整-Xss大小

    -Xss:指定每个线程的私有栈大小

五 线程溢出
  • java.lang.OutOfMemoryError: unable to create new native thread
    原因:创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。
    能创建的线程数的具体计算公式如下:

    (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

    MaxProcessMemory 指的是一个进程的最大内存
    JVMMemory JVM内存
    ReservedOsMemory 保留的操作系统内存
    ThreadStackSize 线程栈的大小

六 地址空间不足
  • java.lang.OutOfMemoryError: request {} byte for {}out of swap
其他调参参数

-XX:PrintGC 触发GC时日志打印
-XX:PrintGCDetails 触发GC时日志打印更详细
-XX:UseSerialGC 串行回收
-XX:SurvivorRatio=8 eden:from:to = 8:1:1
-XX:NewRatio=2 新生代:老年代 = 1:2
-XX:MaxMetaspaceSize=20 配置元空间最大内存20M
-XX:+DoEscapeAnalysis 开启逃逸分析(用于JVM对象分配优化-栈上分配)
-XX:+PrintHeapAtGC 打印heap信息在发生gc时
-XX:+EliminateAllocations 标量替换,默认打开

【参考文档】
内存溢出的几种原因和解决办法(转)
Jvm参数调优

猜你喜欢

转载自blog.csdn.net/qq_36281031/article/details/108441495