文章目录
-
- 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,则会执行默认。