关于jvm:JVM-OOM

15次阅读

共计 2059 个字符,预计需要花费 6 分钟才能阅读完成。

既然抉择了远方,即便天寒地冻,路遥马亡,我本就赤贫如洗,又有何惧。

OOM(内存溢出)是一个让人很头疼的问题,呈现 OOM 的问题有很多,上面就 OOM 可能呈现的起因进行介绍。

1、堆空间太小

用以下参数启动 jvm
-Xms20m -Xmx20m

public class OOMTest {public static void main(String[] args) {Byte[] bs = new Byte[1024 * 1024 * 30];
    }
}

最大堆、初始化堆均为 20m,程序创立了 30m 的数组,间接 OOM。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

1.1、解决形式

  1. 调大 -Xmx 的值
  2. 通过内存剖析工具,找出占用内存较多的对象

2、间接内存溢出

间接内存属于堆外内存,是间接向操作系统申请内存空间。
间接内存申请速度个别小于堆内存的申请速度,然而访问速度会比堆内存的访问速度快。
间接内存并没有齐全的归 GC 治理,使用不当,也会造成 OOM

2.1、间接内存不足,溢出

用以下参数启动 jvm
-Xms20m -Xmx20m

public class OOMTest {public static void main(String[] args) {while (true) {ByteBuffer.allocateDirect(1024 * 1024 * 30);
        }
    }
}

间接内存最大值为 20m, 所以间接溢出

Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
    at java.nio.Bits.reserveMemory(Bits.java:694)
    at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
    at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
    at com.csp.boot.jvm.OOMTest.main(OOMTest.java:14)

注:间接内存最大值,默认为 -Xmx 配置的值

2.2、解决形式

  1. 调小 -Xmx 的值,让操作系统有更多的内存调配给间接内存
  2. 防止一次性调配太大的间接内存
  3. 设置正当的 -XX:MaxDirectMemorySize

2.3、间接内存回收

间接内存只有在使用量触到 -XX:MaxDirectMemorySize 时,才会触发 GC,具体看上面 demo

用以下参数启动 jvm
-Xms20m -Xmx20m -verbose:gc

public class OOMTest {public static void main(String[] args) {while (true) {ByteBuffer.allocateDirect(1024 * 1024 * 1);
        }
    }
}

启动后,会在程序控制台,看到有 GC 日志一直的输入

[GC (System.gc())  2474K->731K(19968K), 0.0016716 secs]
[Full GC (System.gc())  731K->631K(19968K), 0.0043987 secs]

3、线程过多

在 java 内存模式中, 虚拟机栈,本地办法栈,程序计算器 这些都是线程独有的,线程自身也占用内存空间,如果线程启用太多,会间接导致 OOM

用以下参数启动 jvm
-Xms20m -Xmx20m

public class OOMTest {public static void main(String[] args) {while (true) {new Thread(() -> {
                try {Thread.sleep(30000);
                } catch (InterruptedException e) {e.printStackTrace();
                }
            }).start();}
    }
}
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:717)
    at com.csp.boot.jvm.OOMTest.main(OOMTest.java:19)

3.1、解决形式

  1. 适当调低 -Xss 的值,可使 jvm 创立更多的线程

4、GC 效率低下

当 GC 效率低下时,也会呈现 oom。GC 效率低下导致的 oom 条件刻薄,然而还是不可避免会呈现

4.1、触发条件

  1. 花在 GC 的工夫上,超过 98%
  2. 老年代开释的内存小于 2%
  3. 新生代开释的内存小于 2%
  4. 间断 5 次 GC 都呈现以上状况

触发后,会抛出以下异样

注:必须满足以上所有条件,才会触发

5、内存泄露

呈现内存泄露的起因,次要是对象曾经无用了,然而却无奈被回收。从而可应用的内存越来越少,最终触发 OOM.

找出内存泄露的罪魁祸首个别须要借助内存剖析工具,进行剖析。这一部分的内容比拟多,会放到下一章节来说。

正文完
 0