JVM – OOM

既然选择了远方,即使天寒地冻,路遥马亡,我本就一无所有,又有何惧。

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、处理方式

-Xmx

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、处理方式

-Xmx
-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 .

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

SegmentFault博客
我还没有学会写个人说明!
上一篇

北京环球影城核心工程已完工 已进入运营筹备阶段

下一篇

云原生景观:编排和管理层解决了什么问题?如何解决的?

你也可能喜欢

评论已经被关闭。

插入图片