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),正在運行的進程直接被終止,沒有機會執行收尾操作

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章