<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          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.

          意思就是說(shuō)可以給?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è)的鉤子。也就是說(shuō),在程序主線程(實(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í)行。

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

          javadoc?也給出了這種情況的說(shuō)明:

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

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

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

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

          也就是說(shuō),虛擬機(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è)特性,可以定制出來(lái)很多使用場(chǎng)景。

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

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

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

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

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

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

            • ??這時(shí)因?yàn)楫?dāng)用戶注銷或者關(guān)機(jī)時(shí),底層操作系統(tǒng)可能只允許有限的固定時(shí)間來(lái)關(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)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费看黄色片视频 | 国产国产日韩欧美V∧ | 欧美丁香五月天 | 亚洲无码不卡视频在线观看 | 人人看人人摸人人草 |