我從另一個問題中借用了這個:
@Slf4j
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
public void run() {
try {
//do some stuff
LOG.debug("about to throw a RE from a worker thead");
} catch (Exception e) {
e.printStackTrace();
}
throw new RuntimeException("purposeful!");
}
};
LOG.debug("in main thead");
t.setUncaughtExceptionHandler(
(thread, throwable) -> LOG.debug("in main thread; catching exception from worker. uncaught exception from worker thread: {} from {}",
throwable.getMessage(), thread.getName()));
t.start();
TimeUnit.SECONDS.sleep(10);
LOG.debug("done-main thead");
}
}
如果它運行,將產生以下輸出:
10:19:50.249 [main] DEBUG com.foo.services.search.Main - in main thead
10:19:50.258 [Thread-0] DEBUG com.foo.services.search.Main - about to throw a RE from a worker thead
10:19:50.258 [Thread-0] DEBUG com.foo.services.search.Main - in main thread; catching exception from worker. uncaught exception from worker thread: purposeful! from Thread-0
10:20:00.258 [main] DEBUG com.foo.services.search.Main - done-main thead
為什么,當執行緒 0 完成時,throwable-捕獲活動似乎發生在這個已完成的執行緒內?
uj5u.com熱心網友回復:
JDK的form doc,宣告這個方法只被JVM呼叫:
/**
* Dispatch an uncaught exception to the handler. This method is
* intended to be called only by the JVM.
*/
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
出于好奇,我找到了hotspot的相關原始碼:https : //github.com/openjdk/jdk/blob/master/src/hotspot/share/runtime/thread.cpp
正如您在 中看到的thread.cpp,thread退出時會觸發此邏輯:
// For any new cleanup additions, please check to see if they need to be applied to
// cleanup_failed_attach_current_thread as well.
void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
// ........
if (!destroy_vm) {
if (uncaught_exception.not_null()) {
EXCEPTION_MARK;
// Call method Thread.dispatchUncaughtException().
Klass* thread_klass = vmClasses::Thread_klass();
//...
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/362860.html
