Shutdown Hooks可以在JVM shutting down的时候,运行一段代码,如果一些场景需要我们在JVM挂了的时候,执行一些特殊的清理工作,那我们就可以使用它了。
但是如果VM是因为外部(例如linux下面的kill -9)或者资源问题(例如out of memory)引起的shutting down,那它也无法被触发。
Shutdown Hook使用起来非常简单,我们只需要继承java.lang.Thread
类,然后实现run方法,然后调用Runtime.getRuntime().addShutdownHook(Thread)
。如果在运行过程中想要移除Shutdown Hook,只需要调用Runtime.getRuntime().removeShutdownHook(Thread)
方法。例子如下:
public class TestHook{
public static void main(String[] args){
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Shutdown Hook is running !");
}
});
System.out.println("Application Terminating ..."); }
}
}
执行结果为:
Application Terminating ...
Shutdown Hook is running !
Shutdown Hook虽然用起来很简单,但是它还是有很多坑的。
它不是在任何时候都能执行
如果JVM是由于内部原因的,例如out of memory,那么它将会无法执行。如果是操作系统将JVM杀掉了,它也无法执行。还有如果是通过调用
Runtime.halt()
方法,可能也会导致Shutdown Hook无法运行。它只有当应用是正常结束(调用Syatem.exit()或者所有的线程都结束)的时候才能够执行。当然,如果应用程序是通过
Ctrl+C
、kill命令(除了kill -9)、操作系统shutting down。一旦开始执行,Shutdown Hooks能够在完成之前被强制结束
虽然Shutdown Hook已经开始执行了,但是如果操作系统shutdown的话,它还是会被终结。因此要保证Shutdown Hook能够快速执行完,并且不会造成死锁等情况。
可以添加多个Shutdown Hook,但是无法保证它们的执行顺序。
无法在Shutdown Hook执行
addShutdownHook
或者removeShutdownHook
。- 如果Shutdown Hook开始执行,那么只能通过
Runtime.halt()
去终止。 - 使用Shutdown Hook需要Security permission。否则会发生SecurityException。
- 在Shutdown Hook中抛出的异常与其它代码抛出的异常是一样的。
值得注意的是,最好不要依靠Shutdown Hook来做一些重要的事情,因为它不一定会运行。但是如果希望在主机崩溃、断电的时候执行一些清理操作,那Shutdown Hook将是一个好的选择。