一个线程OOM后,其他线程是可以正常运行的,但是内存泄露之后可能会导致整个程序内存溢出,最终程序不可用。
那么大家下面说一下,一个线程OOM了,为什么其他线程不受影响呢?
要回答这个问题,大家先来回想一下java的内存结构。如下图所示:
大家知道,多线程的时候,每个线程都拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。堆是线程共享的,所以理论上一个线程OOM了,其他线程应该受影响才对啊,实际上却并不是,这是什么原因呢?
有兴趣的可以按照偶下面的这段代码自己去跑一下,测试一下这个内存溢出。
然后结合JvisualVM工具,你会看到,在程序内存溢出之后,溢出的内存的线程所占的内存会被快速释放。如下图所示
根据上图,大家可以得出当一个线程抛出OOM异常后,它所占据的内存资源会被快速的释放掉,从而不会影响其他线程的运行!
另外当一个线程OutOfMemoryError后,如果这个OutOfMemoryError被捕获,那么catch之后吞掉的话程序还能试着继续运行。发生OutOfMemoryError之后,只是当前这个线程申请更多的内存的时候不被JVM允许,所以会抛出OutOfMemoryError异常。当抛出OutOfMemoryError异常后,当前这个线程会被退出,它所占的内存会被JVM清理掉。
那么JVM为什么要这么设计呢?
答案是,Java程序通常不是为了适应意外的异常而设计的,OOM之后可能导致应用状态不一致,建议最好重启。