1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        JVM Shutdown Hook

        共 6806字,需瀏覽 14分鐘

         ·

        2023-06-14 13:34

        須彌零一JVM Shutdown Hook

        今天偶然看到?java.lang.Runtime?類的一個(gè)方法?public void addShutdownHook(Thread hook)?。

        它的?javadoc?是這么寫的:

        Registers a new virtual-machine shutdown hook.
        The Java virtual machine shuts down in response to two kinds of events:

        • ??The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or

        • ??The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.

        意思就是說可以給?JVM?注冊(cè)一個(gè)鉤子,這個(gè)鉤子將在虛擬機(jī)關(guān)閉的執(zhí)行。當(dāng)然這個(gè)?關(guān)閉?是有條件的。

        寫個(gè)例子

            
            
              public
              ?
              class
              ?
              ShutdownHookTest
              ?
              {
              

        ???? public ? static ? void ? main ( String [] ?args ) ? {
        ???????? System . out . println ( "Main?thread?start" );
        ???????? Thread ? hook ? = ? new ? Thread ( new ? MyShutdownHook ());
        ???????? Runtime . getRuntime (). addShutdownHook ( hook );
        ???????? System . out . println ( "Main?thread?end" );
        ???? }

        ???? static ? class ? MyShutdownHook ? implements ? Runnable ? {
        ???????? @Override
        ???????? public ? void ? run () ? {
        ???????????? System . out . println ( "--?my?shutdown?hook?start?--" );
        ???????????? try ? {
        ???????????????? System . out . println ( "--?do?hook?task?--" );
        ???????????????? Thread . sleep ( 5 ? * ? 1000L );
        ???????????????? System . out . println ( "--?hook?task?finished?--" );
        ???????????? } ? catch ? ( InterruptedException ?e ) ? {
        ????????????????e . printStackTrace ();
        ???????????? }
        ???????????? System . out . println ( "--?my?shutdown?hook?end?--" );
        ???????? }
        ???? }

        }

        使用?javac?編譯后運(yùn)行,得到的輸出結(jié)果是:

            
            
              Main
              ?thread?start
              
        Main ?thread? end
        -- ? my ?shutdown?hook?start? --
        -- ? do ?hook?task? --
        -- ?hook?task?finished? --
        -- ? my ?shutdown?hook? end ? --

        結(jié)果符合文章剛開始引文的第一個(gè)情況,當(dāng)程序的正常退出時(shí)會(huì)執(zhí)行注冊(cè)的鉤子。也就是說,在程序主線程(實(shí)際上是所有的?demon線程)結(jié)束后,會(huì)啟動(dòng)執(zhí)行鉤子線程。

        程序非執(zhí)行完成推出的例子

        稍微改一下上面的代碼:

            
            
              public
              ?
              class
              ?
              ShutdownHookTest
              ?
              {
              

        ???? public ? static ? void ? main ( String [] ?args ) ? throws ? Exception {
        ???????? System . out . println ( "Main?thread?start" );
        ???????? Thread ? hook ? = ? new ? Thread ( new ? MyShutdownHook ());
        ???????? Runtime . getRuntime (). addShutdownHook ( hook );
        ???????? //?---?改了這里?---
        ???????? Thread . sleep ( 120 ? * ? 1000L );
        ???????? //?--------------
        ???????? System . out . println ( "Main?thread?end" );
        ???? }

        ???? static ? class ? MyShutdownHook ? implements ? Runnable ? {
        ???????? @Override
        ???????? public ? void ? run () ? {
        ???????????? System . out . println ( "--?my?shutdown?hook?start?--" );
        ???????????? try ? {
        ???????????????? System . out . println ( "--?do?hook?task?--" );
        ???????????????? Thread . sleep ( 5 ? * ? 1000L );
        ???????????????? System . out . println ( "--?hook?task?finished?--" );
        ???????????? } ? catch ? ( InterruptedException ?e ) ? {
        ????????????????e . printStackTrace ();
        ???????????? }
        ???????????? System . out . println ( "--?my?shutdown?hook?end?--" );
        ???????? }
        ???? }

        }

        同樣使用?javac?編譯后運(yùn)行。不同的是,在程序啟動(dòng)后按?ctrl + c?停止程序,將得到下面的輸出:

            
            
              Main
              ?thread?start
              
        -- ? my ?shutdown?hook?start? --
        -- ? do ?hook?task? --
        -- ?hook?task?finished? --
        -- ? my ?shutdown?hook? end ? --

        這個(gè)結(jié)果也符合文章開始引文的第二個(gè)情況。當(dāng)虛擬機(jī)用為用戶輸入?^C?時(shí),虛擬機(jī)會(huì)調(diào)用已注冊(cè)的鉤子。

        另外因?yàn)橐蔡岬搅水?dāng)用戶注銷系統(tǒng)關(guān)閉時(shí)也會(huì)調(diào)用已注冊(cè)的鉤子,這里就不做驗(yàn)證了。

        鉤子不能執(zhí)行的情況

        同樣是上面的例子。程序在啟動(dòng)后,打開任務(wù)管理器(Windows),找到對(duì)應(yīng)的進(jìn)程并結(jié)束。這時(shí)控制臺(tái)的輸出為:

            
            
              Main
              ?thread?start
            
          

        從輸出可以看到,鉤子并沒有執(zhí)行。

        這就說明,在虛擬機(jī)中止?(注意:這里的中止不同于退出或停止,是指異常的break)?的情況下,鉤子不會(huì)被調(diào)用執(zhí)行。

        javadoc?也給出了這種情況的說明:

        在極少數(shù)虛擬機(jī)被外部中止的情況下,例如:

        • ??在 Unix 上使用 SIGKILL 信號(hào)

        • ??在 Windows 上使用 TerminateProcess 調(diào)用

        • ??執(zhí)行本地方法出錯(cuò)

        也就是說,虛擬機(jī)在沒有干凈地關(guān)閉的情況下停止運(yùn)行,虛擬機(jī)則不能保證是否正確的運(yùn)行關(guān)機(jī)鉤子。

        移除鉤子

        移除鉤子使用方法?public boolean removeShutdownHook(Thread hook)?即可。

        使用場(chǎng)景

        看到這個(gè)特性,第一個(gè)想到的場(chǎng)景就是。程序在關(guān)閉時(shí)可以記錄一個(gè)日志或發(fā)送一個(gè)通知。

        當(dāng)然,這個(gè)基于這個(gè)特性,可以定制出來很多使用場(chǎng)景。

        但是,鑒于這個(gè)鉤子的執(zhí)行時(shí)機(jī),就有很多需要注意的地方:

        • ??關(guān)機(jī)鉤子(shutdown hook)必須是一個(gè)已初始化但未啟動(dòng)的線程

        • ??如果注冊(cè)了多個(gè)鉤子,則不能保證這些鉤子的執(zhí)行順序,他們是同時(shí)開始的

        • ??當(dāng)虛擬機(jī)關(guān)機(jī)序列開始,則無法在注冊(cè)或取消鉤子

        • ??對(duì)于鉤子的線程的編寫,應(yīng)該是線程安全的,并盡可能地避免出現(xiàn)死鎖

        • ??鉤子的執(zhí)行時(shí)間不應(yīng)過長,也不應(yīng)該添加任何用戶交互功能

          • ??這時(shí)因?yàn)楫?dāng)用戶注銷或者關(guān)機(jī)時(shí),底層操作系統(tǒng)可能只允許有限的固定時(shí)間來關(guān)閉和退出虛擬機(jī)

        最后

        文章就寫到這里。

        這篇文章沒啥深入的探究,只是突然發(fā)現(xiàn)了一個(gè)之前未曾注意到的功能,簡(jiǎn)單的做一下記錄和測(cè)試。

        大家如果要在生產(chǎn)環(huán)境中使用,要是場(chǎng)景復(fù)雜還是慎重些,上一章節(jié)的那些注意事項(xiàng)都需要考慮考慮。

        ---- END ----

        歡迎關(guān)注我的公眾號(hào)“須彌零一”,原創(chuàng)技術(shù)文章第一時(shí)間推送。

        瀏覽 60
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            在线免费日本中文亚洲 | 美国美女操逼 | www欧美精品 | 就爱操影院 | 黄色无码免费观看 | 国产无遮挡呻吟吸乳视频 | 国产精品毛片A | 国产精品入口免费 | 豆花视频免费在线观看 | 婷婷无码成人精品俺来俺去 |