4

OOM 会不会导致JVM的crash

前提

前几天有公司的大佬分享了一个产线问题:因为VMThread线程阻塞在进入安全点的位置,导致了JVM的crash , 听完我才知道原来JVM的crash会产生一个hs_err_pid的log文件,本来以为自己已经熟知了JVM的知识,没想到还有新的知识点出现,然后我就想自己亲手模拟一下让JVM crash来产生这个hs_err_pid log, 最后我选择了通过OOM来实现
但是我们都知道OOM 只能导致回收掉当前线程,并不会导致JVM crash ,所以我想都没想就写了下面的代码:

代码

import java.util.ArrayList;
import java.util.List;

public class MakeVmAbort {

    static List<Thread> ts = new ArrayList<>();

    static List<byte[]> bs = new ArrayList<>();

    public static void main(String[] args) {

        try {
            while (true) {
                Thread t = new Thread(() -> {
                    while (true) {
                        bs.add(new byte[1024 * 1024]);
                        try {
                            Thread.sleep(500L);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
                t.start();
                ts.add(t);
            }

        } catch (Exception e) {
            System.out.println(e.getStackTrace());
        }
    }

}
//java -Xmx50M -Xms50M -XX:ErrorFile=/home/wks/javacode/java_error.log  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/home/wks/javacode/gc.log

叉腰,不断的new线程,线程不断的产生byte[] ,且专门有两个static 的list来放byte[]和线程,保证不会被GC 掉,这样JVM 应该可以崩溃了吧。

过程

最后发现,JVM确实会退出 ,但是并没有产生 hs_err_pid 的log, 所以问题来了,JVM是怎么退出的,是linux kill掉的吗?我用 egrep -i 'java' /var/log/messages 查了系统日志发现并没有,且我查看了GC log 发现JVM 一直处于 回收不到内存的状态。困惑了很久之后 我在stackOverFlow上提问:

https://stackoverflow.com/que...

大佬一下就点醒了我, JVM最后的退出时因为 while 循环里new Thread 都没有内存支持了,所以main线程都被回收了,而JVM 的退出 是因为 当JVM中不存在 非daemon线程 所以主动关闭的。

此时映衬的我是多么的愚蠢,一个愚蠢的问题硬是搞了这么久。

那回到我的原始目的 ,怎么才能让JVM崩溃那,我最后暗搓搓的加了一个XX:+ CrashOnOutOfMemoryError ,才终于看到生成了 hs_err_pid

结论

所以OOM 会导致JVM崩溃吗,答案是不会,JVM会一直坚挺的运行,即使他已经报 GC overhead limit exceeded(预警GC回收的内存太少) ,那么什么样的错误会导致JVM 的crash那?

我翻看了oracle 的Java troubleshoot 手册

https://docs.oracle.com/javas...

发现

A crash, or fatal error, causes a process to terminate abnormally. There are various possible reasons for a crash. For example, a crash can occur due to a bug in the Java HotSpot VM, in a system library, in a Java SE library or an API, in application native code, or even in the operating system (OS). External factors, such as resource exhaustion in the OS can also cause a crash.
Crashes caused by bugs in the Java HotSpot VM or in the Java SE library code are rare.

所以引起crash的原因大概是 JVM 的gub, OS bug ,OS资源的回收。 其实说了和没说一样,太笼统了。

好像写了一篇无聊的记录。。。

散会!!


没有感情的杀手
321 声望7 粉丝

搬砖工程师