首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Runtime Shutdown Hook 深度解析:優雅關閉與資源釋放最佳實踐

     編輯:Java 相關知識

什麼是 Shutdown Hook?

Shutdown Hook 是已初始化但未啟動的執行緒,註冊至 Runtime.getRuntime()。當 JVM 正常關閉時,這些 Hook 會並發啟動並執行清理邏輯。

註冊 API

Runtime.getRuntime().addShutdownHook(Thread hook);
  • Hook 必須是 Thread 實例(通常實作 Runnable)。
  • 可註冊多個 Hook,JVM 不保證執行順序。
  • Hook 應快速完成,避免耗時操作導致關閉超時。

完整範例

package john2;

public class ShutdownHookDemo implements Runnable {
    public ShutdownHookDemo() {
        // 註冊 hook
        Runtime.getRuntime().addShutdownHook(new Thread(this));
        System.out.println(">>> Shutdown hook registered");
    }

    @Override
    public void run() {
        System.out.println("\n>>> Executing cleanup before JVM exit...");
        cleanUp();
        System.out.println(">>> Cleanup finished.");
    }

    private void cleanUp() {
        // 模擬釋放資源:關閉連線池、刷新日誌、保存狀態等
        for (int i = 0; i < 5; i++) {
            System.out.println("Cleanup step " + (i+1));
            try { Thread.sleep(200); } catch (InterruptedException ignored) {}
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new ShutdownHookDemo();
        System.out.println(">>> Sleeping 5s, try Ctrl+C to trigger hook...");
        Thread.sleep(5000);
        System.out.println(">>> Main thread exiting, JVM will shutdown.");
    }
}

觸發 Shutdown Hook 的場景

  1. System.exit(int) 被呼叫
  2. 用戶在控制台按 Ctrl+C (SIGINT)
  3. 最後一個非守護執行緒結束
  4. 用戶登出或系統關機 (SIGTERM)

不會執行 Hook 的場景

  • JVM Crash(如 Segfault、OOM 導致 VM 崩潰、藍屏)
  • 呼叫 Runtime.halt() 強制終止
  • kill -9 (SIGKILL) 強制殺死進程

效能與資源佔用

Hook 執行緒在註冊時未啟動,不佔用 CPU/記憶體資源(除 Thread 物件本身)。僅在關閉時啟動,對運行期零影響。

最佳實踐

  1. 冪等性:清理邏輯需可重複執行(如關閉已關閉的連線不報錯)。
  2. 超時控制:單個 Hook 執行時間過長可能導致 JVM 強制退出,建議 < 5 秒。
  3. 避免死鎖:Hook 間不應有鎖依賴;若需協調,主程式應在 System.exit() 前手動協調。
  4. 守護執行緒不影響關閉:只有非守護執行緒全結束才觸發關閉流程。
  5. Spring/框架整合:Spring 的 ConfigurableApplicationContext.registerShutdownHook() 內部即使用此機制關閉容器。

常見錯誤

// 錯誤:在 Hook 中啟動新執行緒做耗時任務
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    new Thread(() -> heavyCleanup()).start(); // 主 Hook 結束,JVM 可能直接退出,子執行緒被殺
}));

// 正確:在 Hook 內同步完成,或使用 CountDownLatch 等待關鍵非守護執行緒
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved