2011-12-19 74 views
5

如果存在熱點崩潰,是否有辦法確保整個Java進程將退出?如何強制Java進程在熱點崩潰時退出

爲了進程隔離,我們在遠程Windows Java進程(java.exe)中託管本地庫。然而,我們發現,即使在熱點崩潰時,儘管主線程會因熱點崩潰而「死亡」,但進程本身並不會死亡。我們必須在任務管理器中將其關閉。

我們認爲這可能是因爲本地庫本身創建了自己的線程,它們使進程保持活動狀態。

如果存在熱點崩潰,我們希望整個Java進程死掉。

我們目前的工作是讓另一個線程讀取派生進程的輸出(我們必須讀取控制檯輸出以阻止進程阻塞)。我們修改它也明確地尋找一個虛擬機崩潰:

private static String HOTSPOT_CRASH = "# A fatal error has been detected by the Java Runtime Environment"; 

public void run() { 
    try { 
     BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 
     String line; 
     do { 
      line = reader.readLine(); 
      if (line != null) { 
       logger.info(prefix + ": " + line); 
      } 
      if(line.contains(HOTSPOT_CRASH)) { 
       logger.error(String.format("FATAL Hotspot crash detected. Killing child process '%s'...", hostProcess)); 
       hostProcess.destroy(); 
      } 
     } while (line != null); 
     reader.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

但是,這是一個黑客:如果JVM知道夠註銷,有已經有碰撞,它會好得多,如果它可以告訴也終止當前進程。

有沒有辦法做到這一點?理想情況下,它將是JVM的命令行選項。

+3

進程無法部分崩潰。你幾乎肯定有兩個進程。 – 2011-12-19 09:52:40

+0

有趣的問題!崩潰是一場崩潰,所以如果發生這種事情你不會做太多事情。我可能會建立一個心跳監視器(孩子向父母發送ping消息,父母每隔幾分鐘發送一次乒乓)。在沒有心跳的情況下退出。 – aishwarya 2011-12-19 10:22:29

+0

@Ingo - 不幸的是我也這麼認爲。但事實證明,我們正在發生熱點事故,但這個過程仍然存在。只有我們在任務管理器中殺死它,它才真正消失。 – 2011-12-19 12:50:07

回答

0

通常,當檢測到致命錯誤時,虛擬機將退出,但您可以在代碼中防止出現此錯誤。這裏有幾條線索:

  • 檢查父進程。在Unix上,只有當父進程處理SIGCHLD信號時(它告訴父節點子節點已經終止;這允許父進程讀取退出代碼),子節點纔會死亡。

    請確保您處理輸出,並在兒童死亡後至少調用waitFor()一次。這應該清理子進程。

  • 尋找非守護線程。如果您的Java應用程序中有任何非守護線程,它們可以阻止VM退出。

    但是VM錯誤會終止所有線程,所以我的猜測是你永遠不會清理子進程。

+0

我們通過TCP套接字與子進程進行通信。如果子進程遇到熱點錯誤,我們希望正在從套接字讀取的父進程中的線程獲得一個「逐個連接重置」消息。一旦得到了,我們可以清理子進程。 – 2011-12-19 13:55:33

+0

目前的問題是,父進程無法知道子進程已經崩潰:套接字「讀」調用只是等待直到我們終止任務管理器中的進程。 – 2011-12-19 13:56:24