簡體   English   中英

JVM終止后會發生什么?

[英]What happens when the JVM is terminated?

使用System.exit(0)^C或類似的任何東西終止JVM時會發生什么? 我讀過“過程剛被吹走”和“每一個線程都被停止”之類的東西,但我想知道究竟發生了什么。 我已經知道有一些shutdownHook仍然會被執行,但是在調用shutdownHooks之前會發生什么,並且在所有這些線程完成之后會發生什么?

我想正確地實現這樣的shutdownHook ,並且這樣做我需要對可能仍然執行的內容和不執行的內容做出正確的假設。


更新:

一些代碼:

class SomeObject {

    private boolean stopped;

    SomeObject() {
        stopped = false;
        Thread hook = new Thread() {

            @Override
            public void run() {
                stopped = true;
            }

        };
        hook.setPriority(Thread.MAX_PRIORITY);
        Runtime.getRuntime().addShutdownHook(hook);
    }

    boolean map(Iterator<Object> it) {
        while(it.hasNext() && !stopped) {
            writeToOtherObject(it.next());
            it.remove();
        }
        //have calculations finished?
        return !it.hasNext();
    }
}

map函數計算在其他對象中收集的結果。 在破壞所有內容之前,應將此對象存儲在某個文件中(通過普通優先級shutdownHook也是如此)。 shutdownHook在這里有意義嗎? 據我所知,所有線程首先被銷毀,然后才運行shutdownHook (同時,但我假設首先運行高優先級線程......)然后最終確定對象。 這使得上面的代碼相當無用,因為這個shutdownHook的目的是確保在關閉已經開始時沒有啟動新的循環。 我的理解是正確和完整的嗎?

讓我們從可以啟動關閉序列的不同方式開始:

  • 最后一個非守護程序線程結束。
  • JVM被中斷(通過使用ctrl C或發送SIGINT)。
  • JVM終止(通過發送SIGTERM)
  • 其中一個線程調用System.exit()Runtime.exit()

調用System.exit(int) ,它調用Runtime.exit() 它檢查安全管理器是否允許以給定狀態退出,如果是,則調用Shutdown.exit()

如果您中斷了JVM或系統向其發送了TERM信號,則默認情況下,直接調用Shutdown.exit()而不檢查安全管理器。

Shutdown類是java.lang的內部包私有類。 除其他外,它有exit()halt()方法。 它的exit()方法做了一些事情來阻止鈎子被執行兩次,依此類推,但基本上,它的作用是什么

  1. 運行系統掛鈎。 系統掛鈎由JRE方法在內部注冊。 它們按順序運行,而不是在線程中運行。 第二個系統掛鈎運行您添加的應用程序掛鈎。 它將每個作為一個線程啟動,然后在最后為每個線程提供一個join 其他系統掛鈎可以在應用程序掛鈎之前或之后運行。
  2. 如果終結者應該在停止之前運行,那么它們就會被運行。 這通常不會發生,因為該方法已被棄用。 如果退出的狀態不是零,則無論如何都會忽略runFinalizersOnExit
  3. JVM停止了。

現在,與您的假設相反,在第3階段,所有線程都停止了。 halt方法是本機的,我沒有嘗試讀取本機代碼,但是直到它被調用的那一刻,運行的唯一代碼是純Java,並且沒有任何東西可以阻止其中的任何地方的線程。 Runtime.addShutdownHook文檔實際上說:

關閉鈎子只是一個初始化但未啟動的線程。 當虛擬機開始其關閉序列時,它將以某種未指定的順序啟動所有已注冊的關閉掛鈎,並讓它們同時運行。 當所有掛鈎都完成后,如果啟用了finalization-on-exit,它將運行所有未讀取的終結器。 最后,虛擬機將停止。 請注意,守護程序線程將在關閉序列期間繼續運行,如果通過調用exit方法啟動關閉,則非守護程序線程也將繼續運行。

(強調我的)

所以你看,它確實是關閉鈎子的工作的一部分,告訴線程他們應該離開他們的循環並清理。

另一個誤解是關於給線程一個高優先級。 高優先級並不意味着線程將在所有其他掛鈎之前首先運行。 它只是意味着每當操作系統必須決定哪個線程處於“准備運行”狀態以給CPU運行時,高優先級線程將具有更高的“獲勝”概率 - 取決於關於操作系統的調度算法。 簡而言之,它可能會獲得更多的CPU訪問權限,但它不會 - 特別是如果你有多個CPU核心 - 必須在其他線程之前啟動或在它們之前完成。

最后一件事 - 如果你想使用一個標志告訴一個線程停止工作,那個標志應該是volatile

看看DZone的這篇文章 它詳細介紹了JVM及其終止,重點介紹了ShutdownHook的使用。

從較高層面來看,它涵蓋的一些重要假設包括:

  1. 在某些情況下可能無法執行關機掛鈎!
  2. 一旦啟動,可以在完成之前強制停止關機掛鈎。
  3. 您可以擁有多個Shutdown Hook,但不保證其執行順序。
  4. 您無法在Shutdown Hooks中注冊/取消注冊Shutdown Hooks
  5. 一旦關閉序列啟動,它只能由Runtime.halt()停止。
  6. 使用關閉掛鈎需要安全權限。
  7. Shutdown Hooks拋出的異常與任何其他代碼段拋出的異常一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM