原文出處:http://kim-miao.iteye.com/blog/1662550。感謝做者的無私分享。html
一.Runtime.addShutdownHook理解java
在看別人的代碼時,發現其中有這個方法,便順便梳理一下。api
void java.lang.Runtime.addShutdownHook(Thread hook)安全
該方法用來在jvm中增長一個關閉的鉤子。當程序正常退出,系統調用 System.exit方法或虛擬機被關閉時纔會執行添加的shutdownHook線程。其中shutdownHook是一個已初始化但並不有啓動的線程,當jvm關閉的時候,會執行系統中已經設置的全部經過方法addShutdownHook添加的鉤子,當系統執行完這些鉤子後,jvm纔會關閉。因此可經過這些鉤子在jvm關閉的時候進行內存清理、資源回收等工做。 數據結構
二.示例代碼jvm
輸出以下:編碼
我在這裏附上JDK api上關於這個方法的說明,看這個api以爲有點繞。spa
=========================================================================================================操作系統
public void addShutdownHook(Thread hook)
Java 虛擬機會爲了響應如下兩類事件而關閉:.net
exit
(等同於 System.exit
)方法時。或者, 關閉鉤子 只是一個已初始化但還沒有啓動的線程。虛擬機開始啓用其關閉序列時,它會以某種未指定的順序啓動全部已註冊的關閉鉤子,並讓它們同時運行。運行完全部的鉤子後,若是已啓用退出終結,那麼虛擬機接着會運行全部未調用的終結方法。最後,虛擬機會暫停。注意,關閉序列期間會繼續運行守護線程,若是經過調用 exit
方法來發起關閉序列,那麼也會繼續運行非守護線程。
一旦開始了關閉序列,則只能經過調用 halt
方法來中止這個序列,此方法可強行終止虛擬機。
一旦開始了關閉序列,則不可能註冊新的關閉鉤子或取消註冊先前已註冊的鉤子。嘗試執行這些操做會致使拋出 IllegalStateException
。
關閉鉤子可在虛擬機生命週期中的特定時間運行,所以應保護性地對其進行編碼。特別是應將關閉鉤子編寫爲線程安全的,並儘量地避免死鎖。關閉鉤子還應該不盲目地依靠某些服務,這些服務可能已註冊了本身的關閉鉤子,因此其自己可能正處於關閉進程中。例如,試圖使用其餘基於線程的服務(如 AWT 事件指派線程)可能致使死鎖。
關閉鉤子應該快速地完成其工做。當程序調用 exit
時,虛擬機應該迅速地關閉並退出。因爲用戶註銷或系統關閉而終止虛擬機時,底層的操做系統可能只容許在固定的時間內關閉並退出。所以在關閉鉤子中嘗試進行任何用戶交互或執行長時間的計算都是不明智的。
與其餘全部線程同樣,經過調用線程 ThreadGroup
對象的 uncaughtException
方法,可在關閉鉤子中處理未捕獲的異常。此方法的默認實現是將該異常的堆棧跟蹤打印至 System.err
並終止線程;它不會致使虛擬機退出或暫停。
僅在不多的狀況下,虛擬機可能會停止,也就是沒有徹底關閉就中止運行。虛擬機被外部終止時會出現這種現象,好比在 Unix 上使用 SIGKILL 信號或者在 Microsoft Windows 上調用 TerminateProcess。若是因爲內部數據結構損壞或試圖訪問不存在的內存而致使本機方法執行錯誤,那麼可能也會停止虛擬機。若是虛擬機停止,則沒法保證是否將運行關閉鉤子。
hook
- 一個已初始化但還沒有啓動的
Thread
對象
IllegalArgumentException
- 若是指定的鉤子已註冊,或者能夠肯定鉤子正在運行或者已運行完畢
IllegalStateException
- 若是虛擬機已經處於關閉進程中
SecurityException
- 若是安全管理器存在而且拒絕
RuntimePermission
("shutdownHooks")