文章目錄
-
- Hook線程
- 線程運作時異常
Hook線程
JVM
程序退出是由于
JVM
程序中沒有活躍的非守護線程,或者收到了系統中斷信号,向
JVM
程式注入一個
Hook
線程,在
JVM
程序退出的時候,
Hook
線程會啟動執行,通過
Runtime
可以為
JVM
注入多個
Hook
線程。
示例
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread(()->{
try {
System.out.println("the hook thread 1 is running.");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("the hook thread 1 will exit.");
}));
Runtime.getRuntime().addShutdownHook(new Thread(()->{
try {
System.out.println("the hook thread 2 is running.");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("the hook thread 2 will exit.");
}));
System.out.println("The program will is stopping.");
}
輸出
The program will is stopping.
the hook thread 1 is running.
the hook thread 2 is running.
the hook thread 1 will exit.
the hook thread 2 will exit.
注意事項
-
線程隻有在收到退出信号的時候會被執行,如果在 kill 的時候使用了參數 -9,那麼Hook
線程不會得到執行,程序将會立即退出。Hook
-
線程中也可以執行一些資源釋放的工作。Hook
- 盡量不要再
線程中執行一些耗時非常長的操作,因為其會導緻程式遲遲不能退出。Hook
線程運作時異常
API
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) //某個線程指定 UncaughtExceptionHandler
public UncaughtExceptionHandler getUncaughtExceptionHandler() //擷取該線程指定的UncaughtExceptionHandler
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) //設定全局線程 UncaughtExceptionHandler
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() //擷取全局線程 UncaughtExceptionHandler
UncaughtExceptionHandler
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
* <p>Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
該接口會被
Thread
中的
dispatchUncaughtException
方法調用。
dispatchUncaughtException
方法隻會被
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);
}
getUncaughtExceptionHandler
方法
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
其中
uncaughtExceptionHandler
變量為該線程指定的
UncaughtExceptionHandler
,即調用
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)
方法設定。
group
為線程組,其實作了
Thread.UncaughtExceptionHandler
接口。預設的
uncaughtException
方法為:
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}
}
如果父線程組不為 null ,會一直擷取執行父線程組的
uncaughtException
方法,如果父線程組為 null ,則擷取預設的,如果預設的不為 null,則會執行預設。