未處理的運行時例外會停止整個服務器(即 Spring Boot 應用程式)還是僅停止特定的 HTTP 請求?
確實,未處理的運行時例外會立即關閉正常的 Java 應用程式,對嗎?
uj5u.com熱心網友回復:
只是有問題的執行緒
未處理的RuntimeException將殺死執行緒,而不是應用程式。通常每個 HTTP 請求都由它自己的執行緒處理,因此服務器中的其他任何內容都不應該受到影響。我不知道服務器如何處理死執行緒。明智的做法可能是為即將到來的請求創建一個新執行緒。
只有當所有執行緒(所謂的惡魔執行緒除外)都終止時,您的 Spring Boot 應用程式才會停止。這反過來意味著在一個沒有執行緒的應用程式中——一個所有東西都在主執行緒中運行的應用程式——一個未捕獲的例外(RuntimeException或其他型別)將導致整個程式停機。
在大多數應用程式中,哪個執行緒被殺死很重要。您的應用程式可能有更多執行緒處理 HTTP 請求,并且可以根據需要產生新的執行緒。在這種情況下,除非用戶發送了這個 HTTP 請求,否則幾乎不會注意到執行緒死亡。其他執行緒可能對服務器的運行更重要,而這樣的執行緒被殺死,雖然不會完全停止服務器,但會阻止它正常作業。對于不同的示例,如果桌面應用程式中的事件調度執行緒被例外殺死,則該應用程式將無法再接受用戶輸入。
自己試試吧
不需要太多嘗試。下面的程式產生一個執行緒,拋出一個未處理的例外。
public class DemoUnhandledException {
public static void main(String[] args) throws InterruptedException {
new Thread(() -> { throw new RuntimeException("Demo"); }).start();
TimeUnit.MINUTES.sleep(1);
System.out.println("A minute later the main thread is still alive and well");
}
}
讓程式運行一整分鐘以獲得完整的輸出,即:
Exception in thread "Thread-0" java.lang.RuntimeException: Demo at ovv.so.exception.DemoUnhandledException.lambda$0(DemoUnhandledException.java:8) at java.base/java.lang.Thread.run(Thread.java:834) A minute later the main thread is still alive and well
關聯
Javamex 上的Java 如何處理未捕獲的例外
uj5u.com熱心網友回復:
這與您的主要問題無關……但您也提出了這個問題。
確實,未處理的運行時例外會立即關閉正常的 Java 應用程式,對嗎?
其實不對。
未捕獲的例外會導致拋出例外的執行緒終止。在一個簡單的 Java 應用程式中,只有一個(非守護行程)“主”執行緒,并且在該執行緒上發生了一個未捕獲的例外,JVM 然后退出,因為最后一個非守護行程執行緒已經終止。
但是如果有其他執行緒......未捕獲的例外不會停止JVM。
為了說明,運行這個程式:
public class Test {
public static void main(String[] args) {
new Thread(() -> {
try {
Thread.sleep(10000);
} catch (Exception e) {
System.err.println("Caught " e);
}
}).start();
throw new RuntimeException("Goodbye cruel world");
}
}
當您運行它時,您將觀察到堆疊跟蹤列印(來自 中未捕獲的例外main)和程式實際結束之間有 10 秒的延遲。JVM 正在等待子執行緒終止。
這也可以間接回答您的主要問題......除了:
- 我們不確定請求執行緒是否是守護執行緒。
- 我們不確定請求執行緒實際上并沒有捕獲/處理您的請求處理代碼拋出的例外。
可以說一個框架通常會根據拋出的例外是什么來做一些明智的事情。例如,框架可能Error通過嘗試關閉來處理作業執行緒上的例外……基于錯誤可能使 JVM 進入潛在的不安全/不可恢復狀態。
uj5u.com熱心網友回復:
未處理的運行時例外會停止整個服務器(即 Spring Boot 應用程式)還是僅停止特定的 HTTP 請求?
通常有一個thread pool網路服務器來處理所有請求(例如tomcat)。發生在 your 中的未捕獲例外controller最終會在某個地方被捕獲,因此它不會導致worker threadinthread pool被殺死。
Tomcat#AbstractEndpoint#processSocket:
Executor executor = getExecutor();
if (dispatch && executor != null) {
// handle request in thread poll
executor.execute(sc);
}
我做了一個簡單的除錯。假設exception在您的 中發生了未處理controller,那么例外實際上是由FrameworkServlet#processRequest. 捕獲后會被包裹成a NestedServletException,繼續往上層扔。最終,它將被捕獲并列印在StandardWrapperValve#invoke.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/373350.html
上一篇:關系未正確反序列化
