JVM OOM异常会导致JVM退出吗?

2020-05-14  本文已影响0人  7d972d5e05e8

参考文章:JVM OOM异常会导致JVM退出吗?

结论是:OOM是针对线程的,哪个线程OOM了,JVM是释放掉该线程所有的资源。然后其他线程继续运行,JVM不会退出。

JVM退出的条件是:虚拟机内不存在非守护线程。

下面是我的demo测试:

public class OOMTest {

    public static void main(String[] args) throws InterruptedException {
        int i=0;
        while (true){
            if(i > 0){
                System.out.println("main thread");
                Thread.sleep(1000L);
                continue;
            }
            Thread t1 = new Thread(() -> {
                List<OOMObject>  refs = new ArrayList<>();
                while (true){
                    OOMObject o1 = new OOMObject();
                    refs.add(o1);
                    System.out.println("thread-1申请1M");
                    try {
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            Thread t2 = new Thread(() -> {
                List<OOMObject>  refs = new ArrayList<>();
                while (true){
                    OOMObject o1 = new OOMObject();
                    refs.add(o1);
                    System.out.println("thread-2申请1M");
                    try {
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            t1.start();
            t2.start();
            i++;
        }
    }

    static class OOMObject {
        byte[] tempbytes = new byte[1024*1024];
    }

}

运行的结果如下:

thread-1申请1M
main thread
thread-2申请1M
thread-1申请1M
main thread
thread-2申请1M
main thread
thread-1申请1M
thread-2申请1M
main thread
thread-1申请1M
thread-2申请1M
main thread
。。。//省略一些
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
    at com.example.demo.stream.OOMTest$OOMObject.<init>(OOMTest.java:56)
    at com.example.demo.stream.OOMTest.lambda$0(OOMTest.java:24)
    at com.example.demo.stream.OOMTest$$Lambda$1/1104106489.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
//这里看到Thread-0线程OOM了,JVM会结束该线程并释放掉它所占用的内存(几乎是一半内存)。然后t2线程继续执行。

thread-2申请1M
main thread
thread-2申请1M
main thread
thread-2申请1M
main thread
thread-2申请1M
main thread
。。。//省略一些
Exception in thread "Thread-1" java.lang.OutOfMemoryError: Java heap space
    at com.example.demo.stream.OOMTest$OOMObject.<init>(OOMTest.java:56)
    at com.example.demo.stream.OOMTest.lambda$1(OOMTest.java:38)
    at com.example.demo.stream.OOMTest$$Lambda$2/812265671.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
//这个时候t2线程也OOM了,JVM结束t2并释放它所占内存。并让主线程继续执行。
main thread
main thread
main thread
main thread
main thread
main thread
main thread
main thread

上面从日志打印来验证的。我们来从JVM的gc看:


image.png

这个图执行的时间有点久,所以你可以看到最后main thread在执行的时候,old几乎为空。这个不用管,重点看下红色框框的内容。
在第一个红色框,old满的之后,立即清理掉t1所占空间,以让t2继续执行。然后t2继续填满t1释放的内存后,它自己也OOM了。JVM释放t2所占内存,那就几乎是所有空间了。所以,main线程运行的时候old几乎为空。

PS:查看上图的gc用jvisualvm,但是需要给它安装个插件Visual GC。

安装插件文档:https://pan.baidu.com/s/19IeeGQnKcYEVpOqJtRsd_w,提取码:uzr1

上一篇下一篇

猜你喜欢

热点阅读