我也来说说经典面试题目-“OOM异常会导致JVM退出吗?”
經(jīng)典面試題目“OOM異常會導(dǎo)致JVM退出嗎?
我的回答是“這要分情況看,對于守護(hù)線程來說,OOM并不會導(dǎo)致JVM退出;對于非守護(hù)線程來說,如果某個線程捕獲了OOM異常并正確進(jìn)行了處理,那JVM并不會退出;如果線程沒有捕獲異常,那么將由全局的異常處理器處理,默認(rèn)的全局的異常處理器也會讓當(dāng)前這個發(fā)生異常的線程退出,但是如果這個線程是最后一個非守護(hù)線程,那么JVM會退出,如果不是,JVM并不會退出。
對于守護(hù)線程來說,OOM并不會導(dǎo)致JVM退出,這里有一個非常好的線上故障:https://blog.csdn.net/shuxiaohua/article/details/114658325 ,缺少的接收客戶端請求的線程Acceptor是一個守護(hù)線程,并且因?yàn)镺OM退出時,并沒有讓Tomcat退出。
下面介紹一下非守護(hù)線程的情況,這些非守護(hù)線程通常就是處理業(yè)務(wù)的線程。每一個寫過Java的人都應(yīng)該知道Java異常繼承體系,如下圖所示。
這里我們要注意一點(diǎn),就是Exception和Error有共同的父類Throwable,這意味著異常和錯誤都可以在Java層捕獲,例如:
public static void main(String[] args) throws InterruptedException {
try{
// 每個整數(shù)數(shù)組的大小為4M
int[] array1 = new int[1_000_000];
int[] array2 = new int[1_000_000];
int[] array3 = new int[1_000_000];
int[] array4 = new int[1_000_000];
int[] array5 = new int[1_000_000];
}catch (Throwable t){
t.printStackTrace();
}
System.out.println("程序走到了這里!");
}
我們在指定參數(shù)-Xms20M -Xmx20m后,運(yùn)行打印結(jié)果如下:
java.lang.OutOfMemoryError: Java heap space
at cn.hotspotvm.TestError.main(TestError.java:12)
程序走到了這里!
可以看到,即使發(fā)生了錯誤,這個線程依然在正常運(yùn)行,如果我們不對Error進(jìn)行捕獲呢?如下:
public static void main(String[] args) throws InterruptedException {
int[] array1 = new int[1_000_000];
int[] array2 = new int[1_000_000];
int[] array3 = new int[1_000_000];
int[] array4 = new int[1_000_000];
int[] array5 = new int[1_000_000];
System.out.println("程序走到了這里!");
}
再次運(yùn)行后就的打印結(jié)果如下:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at cn.hotspotvm.TestError.main(TestError.java:10)
可以看到,在發(fā)生錯誤時這個線程沒有走到打印語句,而是直接退出了。
這里其實(shí)要說明的是,我們可以設(shè)置一個全局的異常處理器來統(tǒng)一處理,或者優(yōu)先針對某個線程設(shè)置異常處理器,這樣當(dāng)我們忽略了捕獲錯誤時,可以在全局異常處理器中進(jìn)行處理。舉個例子如下:
public static void main(String[] args) throws InterruptedException {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("這里是全局異常處理 "+e.getLocalizedMessage());
}
});
int[] array1 = new int[1_000_000];
int[] array2 = new int[1_000_000];
int[] array3 = new int[1_000_000];
int[] array4 = new int[1_000_000];
int[] array5 = new int[1_000_000];
System.out.println("程序走到了這里!");
}
打印的信息如下:
這里是全局異常處理 Java heap space
這個線程在全局異常處理中如果沒有特殊處理,通常會讓當(dāng)前的線程退出。如果當(dāng)前線程退出,那么JVM會退出嗎?
其實(shí)Java虛擬機(jī)退出的條件是:虛擬機(jī)內(nèi)已經(jīng)沒有了非守護(hù)線程。線程發(fā)生未處理的異常最終導(dǎo)致線程結(jié)束時,如果這個線程是最后一個非守護(hù)線程,則會退出,否則不退出。
更多文章可訪問:JDK源碼剖析網(wǎng)
總結(jié)
以上是生活随笔為你收集整理的我也来说说经典面试题目-“OOM异常会导致JVM退出吗?”的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML5和CSS3基础
- 下一篇: codeup之字符串比较