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