Java运行时的shutdown hook

Hook作为一种回调方式,广泛应用于软件中。

从Java 1.3开始,JVM的Runtime也提供了hook的机制,即shutdown hook。提供给出shutdown hook,在退出JVM的时候,能够执行shutdown hook中定义的必要操作。

1. Runtime的Shutdown Hook的特性

  • 可以注册多个hook,每个都是一个独立的线程
  • 如果有多个Hook,Hook线程之间是没有同步的,线程运行的时序是不可预测的
  • 一旦开始执行Shutdown Hook,即无法再注册或删除其他hook
  • 正在执行的Shutdown Hooks,还可能被外部的SIGTERM信号强制停止
  • 正在执行的Shutdown Hooks,在JVM内部只能通过调用Runtime.halt()停止hook的执行
  • 如果JVM启用了Java Security Managers,则执行Shutdown Hook需要shutdownHooks权限

2. 注册Shutdown Hook的方式

        Runtime.getRuntime().addShutdownHook(
            new Thread(new Runnable() {
                @Override
                public void run() {
                    abc;...
                }
            });
        );

在Java 8以后,还可以采用如下流式方式注册hook:

        Runtime.getRuntime().addShutdownHook(
            new Thread( () -> {
                abc;...
            });
        );

3. 通常,JVM退出的方式有如下

  • 程序正常结束,JVM最后执行System.exit(0);
  • 程序异常结束,JVM最后执行System.exit(1);
  • 程序被外部请求中断退出,如用户执行CTRL+C

对于上述的JVM退出方式,Runtime的shutdown hook都将被执行,然后才真正退出JVM。

但是,Runtime的Shutdown Hook在如下情况下,无法被执行:

  • JVM crashes
  • 外部中断请求发出了kill -9 <PID>的命令
  • 程序执行过程中,主动调用了Runtime.halt();

4. 补充说明SIGTERM信号

kill <PID>发出的SIGTERM信号,该信号会陷入(trappable),正在运行的进程执行收尾操作后,响应该信号停止。

  • kill -2 <PID>等价于CTRL+C,即发出SIGINT信号,该信号会陷入,正在运行的进程执行收尾操作后,响应该信号停止
  • kill -9 <PID>发出SIGKILL信号,该信号不会陷入(not trappable),正在运行的进程直接被终止,没有机会执行收尾操作

 


版权声明:本文为taiyangdao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>