2014-01-29 87 views
0

我想要在java中運行關機鉤子。這個鉤子的目的是寫入程序終止的日誌文件。 Java應用程序被編譯成一個jar文件,並使用批處理文件執行,這意味着應用程序的輸出將轉到cmd.exe窗口。當此cmd窗口關閉時,我希望應用程序記錄它已關閉。在java中運行關機鉤子

該應用程序旨在無限期運行並在特定時間執行某些任務。因此,程序正在「While true」循環內執行一系列檢查。我不明白爲什麼這個鉤子不會記錄應用程序正在關閉!

在main方法有:

final Thread mainThread = Thread.currentThread(); 
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() 
{ 
    @Override 
    public void run() 
    { 
     try { mainThread.join(); } 
     catch (InterruptedException e) { } 
     mission.log("Program Closed.", true); 
    } 
} 
)); 

所有「使命」是,是一個自定義類礦山,做數據記錄的一個實例。當你調用方法「log」時,它有一個BufferedWriter,它調用它的.write(),.newLine()和.flush()方法。

當我殺死批處理窗口時,我似乎無法得到我的日誌文件中的「程序關閉」行。我究竟做錯了什麼?

+1

殺死批處理窗口會殺死進程,但並不會正常停止它。 –

+0

然後,是否根本沒有辦法檢測到批處理文件關閉,並將其輸入日誌?你似乎告訴我,這根本不可能。 – Drifter64

+0

我不認爲有一種方法可以檢測進程中是否有進程被殺死。 –

回答

3

強行終止應用程序,即不是優雅的,所以JVM不知道應用程序正在退出,因此不會調用關閉鉤子。

不幸的是,在Windows中至少沒有辦法提供一種機制來確保鉤子總是被調用。這只是一些可能被調用的東西,但沒有保證。

0

在您的流程退出之前無法始終執行某些操作。例如。如果將插頭從牆上插座拔出,您的計算機將立即關閉。或者,如果操作系統通過從調度程序中刪除CPU時間來終止進程,它也沒有機會。

但是,如果刪除代碼

try { mainThread.join(); } 
    catch (InterruptedException e) { } 

然後它將至少可以針對某些情況下,例如執行過程的正常終止。在這裏檢查主線程是沒有意義的,因爲關閉鉤子是由於主線程完成其工作(它退出main()方法)而執行的,或者主線程將繼續運行,直到JVM決定終止(在外部終止的情況下)。

比較接受的答案How to gracefully handle the SIGKILL signal in Java,其中包含您正在嘗試做的另一個示例。

+0

好的,你鏈接的例子談論* nix和蘋果操作系統。據我所知,Windows沒有相當於「kill -9」。不過,我認爲,關閉我的批處理文件窗口,將相同的kill命令發送給JVM。 (SIGKILL?) – Drifter64

+0

我不知道,但你有沒有嘗試刪除兩行代碼並關閉窗口? –

+0

是的。但是,它仍然不會觸發鉤子,這讓我認爲Jaffar Ramay和Dodd10x是正確的。 – Drifter64

0

關閉窗口會導致進程停止,因此關閉掛鉤將不起作用。

聽起來好像你不想讓這個過程完全死亡。您應該考慮使用除批處理腳本以外的其他內容。您可以從Windows任務計劃程序運行一個可執行jar,並讓它始終在後臺運行 - 除非有人故意殺死java或發生錯誤。在這種情況下,您應該嘗試捕獲異常並以這種方式記錄它們。

0

這裏的每個人都是正確的 - 你不能在程序上記錄強制停止。但是,您可能會考慮使用其他程序來「監視」您的程序並等待它退出。 '觀察者'程序然後可以記錄原始程序的終止,然後退出。