参考:http://blog.yohanliyanage.com/2010/10/know-the-jvm-2-shutdown-hooks/
java doc: http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html
1、ShutdownHook在某些情况下不会运行
ShutdownHook从不不保证一定会运行。当JVM由于内部原因崩溃,或接收到操作系统发送的SIGKILL命令等,关闭钩子来不及运行JVM进程就已经退出。2、ShutdownHook可能在运行过程中被中止
操作系统在关闭过程中,发送SIGTERM命令给JVM,如果JVM不能在一定的时间内结束,例如ShutdownHook执行时间过长等,那ShutdownHook就很有可能在执行过程中被中止。 所以ShutdownHook必须能快速执行完,避免会发生阻塞的IO操作或锁相关的操作。3、当存在多个ShutdownHook时,JVM在执行的时候不保证顺序
在jdk1.5的Shutdown类中,可以看到ShutdownHook都保存在一个HashSet中,JVM退出时迭代整个HashSet并分别调用线程的start方法。并发执行,而不是添加时的顺序。4、在JVM关闭过程中不能添加或者去除ShutdownHook
当JVM开始关闭,则不允许再进行ShutdownHook的添加和删除操作,否则抛出IllegalStateException,即不能在ShutdownHook中添加或去除ShutdownHook。5、不能在ShutdownHook中调用System.exit()
当在ShutdownHook中调用System.exit(),不会停止ShutdownHook反而会卡住整个JVM,只能kill -9强制中止进程(jdk1.5进行了验证)。但可以调用Runtime.halt()。6、ShutdownHook抛出的异常和其他普通异常一样,由Uncaught Exception Handler进行处理
7、如果创建匿名内部线程类作为ShutdownHook线程,则容易发生内存泄漏。
这个是开发中遇到的问题,工具函数以匿名内部类的方式创建了很多ShutdownHook,由于内部匿名类会持有外层类的引用,导致外层类对象也一直无法释放。8、Eclipse中调试shutdownhook
Eclipse的红色的Terminate按钮是强制关闭程序,类似kill -9,没法调用shutdownhook;
变通方法起一个线程开启监听console输入,回车后,调用 System.exit(0);就会触发shutdownhook
private static class ExitThread extends Thread{ public void run() { System.out.println("==============eclipse debug=================="); System.out.println("press ENTER to call System.exit(0) "); System.out.println("==============eclipse debug=================="); try { System.out.println(System.in.read()); } catch (IOException e) { e.printStackTrace(); } System.exit(0); } }