{"id":10021058,"date":"2025-10-30T19:17:53","date_gmt":"2025-10-30T11:17:53","guid":{"rendered":"https:\/\/itmax.cn\/?p=10021058"},"modified":"2025-10-30T19:17:53","modified_gmt":"2025-10-30T11:17:53","slug":"java%e5%b0%8f%e7%9f%a5%e8%af%86-shutdownhook%e4%bc%98%e9%9b%85%e5%85%b3%e9%97%ad","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10021058","title":{"rendered":"java\u5c0f\u77e5\u8bc6-ShutdownHook(\u4f18\u96c5\u5173\u95ed)"},"content":{"rendered":"<h2><strong>\u4e00\u3001\u5148\u63d0\u51fa\u4e00\u4e2a\u95ee\u9898<\/strong><\/h2>\n<p>\u6211\u4eec\u5982\u679c\u5728JVM\u9000\u51fa\u7684\u65f6\u5019\u505a\u4e00\u4e9b\u4e8b\u60c5\uff0c\u6bd4\u5982\u5173\u95ed\u8fdc\u7a0b\u94fe\u63a5\uff0c\u600e\u4e48\u5b9e\u73b0\u5462\uff1f<\/p>\n<h2><strong>\u4e8c\u3001ShutdownHook\u7b80\u4ecb<\/strong><\/h2>\n<p>java\u91cc\u6709\u4e2a\u65b9\u6cd5Runtime.getRuntime#<strong>addShutdownHook<\/strong>\uff0c\u662f\u5426\u4e86\u89e3\u5462?<\/p>\n<p>ShutdownHook\u662f\u4ec0\u4e48\u610f\u601d\u5462\uff0c\u770b\u5355\u8bcd\u89e3\u91ca\u201c<strong>\u5173\u95ed\u94a9\u5b50\u201d\uff0caddShutdownHook<\/strong>\u5c31\u662f\u6dfb\u52a0\u4e00\u4e2a\u5173\u95ed\u94a9\u5b50\uff0c\u8fd9\u4e2a\u94a9\u5b50\u662f\u505a\u4ec0\u4e48\u7684\u5462\uff1f\u80fd\u5426\u89e3\u51b3\u4e0a\u9762\u7684\u95ee\u9898\uff1f<\/p>\n<h3><strong>1\u3001RunTime\u7c7b<\/strong><\/h3>\n<p>\u5148\u770b\u4e00\u4e0b\u770b\u6e90\u7801RunTime#<strong>addShutdownHook<\/strong>\u65b9\u6cd5\u4e0e\u89e3\u91ca\u3002<\/p>\n<h4><strong>1.1 \u65b9\u6cd5\u89e3\u91ca<\/strong><\/h4>\n<p>\u6838\u5fc3\u610f\u601d\uff0c\u5728Java\u865a\u62df\u673a\u5728\u5173\u95ed\u65f6\u4f1a\u89e6\u53d1\u4e00\u4e9b\u81ea\u5df1\u6dfb\u52a0\u7684\u4e8b\u4ef6\u3002<\/p>\n<pre><code>Registers a new virtual-machine shutdown hook.\nThe Java virtual machine shuts down in response to two kinds of events:\nThe program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or\nThe 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.\nA shutdown hook is simply an initialized but unstarted thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. \nWhen all the hooks have finished it will then halt. Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if shutdown was initiated by invoking the exit method.<\/code><\/pre>\n<h4><strong>1.2 \u65b9\u6cd5\u6e90\u7801<\/strong><\/h4>\n<pre><code>  public void addShutdownHook(Thread hook) {\n        @SuppressWarnings(&quot;removal&quot;)\n        SecurityManager sm = System.getSecurityManager();\n        if (sm != null) {\n            sm.checkPermission(new RuntimePermission(&quot;shutdownHooks&quot;));\n        }\n        ApplicationShutdownHooks.add(hook);\n    }<\/code><\/pre>\n<p>\u65b9\u6cd5\u5185\u90e8\u8c03\u7528\u4e86ApplicationShutdownHooks#<strong>add\uff0c<\/strong> \u6211\u4eec\u7ee7\u7eed\u5f80\u4e0b\u770b\u3002<\/p>\n<h3><strong>2\u3001ApplicationShutdownHooks\u7c7b<\/strong><\/h3>\n<h4><strong>2.1 \u6dfb\u52a0\u94a9\u5b50<\/strong><\/h4>\n<pre><code>\n     private static IdentityHashMap&lt;Thread, Thread&gt; hooks;\n     static synchronized void add(Thread hook) {\n        if(hooks == null)\n            throw new IllegalStateException(&quot;Shutdown in progress&quot;);\n        if (hook.isAlive())\n            throw new IllegalArgumentException(&quot;Hook already running&quot;);\n        if (hooks.containsKey(hook))\n            throw new IllegalArgumentException(&quot;Hook previously registered&quot;);\n        hooks.put(hook, hook);\n    }<\/code><\/pre>\n<p>\u6211\u4eec\u6dfb\u52a0\u4e86\u4e00\u4e2a\u94a9\u5b50\uff0c\u8fd9\u4e2a\u94a9\u5b50\u662f\u4e2a\u7ebf\u7a0b\uff0c\u8fd9\u4e2a\u7ebf\u7a0b\u600e\u4e48\u6267\u884c\u7684\u5462\uff1f \u7ee7\u7eed\u770b\u4e00\u4e0b\u6b64\u7c7b\u4e2d\u7684runHooks\u3002<\/p>\n<h4><strong>2.2 \u6267\u884c\u94a9\u5b50<\/strong><\/h4>\n<pre><code>\nstatic void runHooks() {\n        Collection&lt;Thread&gt; threads;\n        synchronized(ApplicationShutdownHooks.class) {\n            threads = hooks.keySet();\n            hooks = null;\n        }\n        for (Thread hook : threads) {\n            hook.start();\n        }\n        for (Thread hook : threads) {\n            while (true) {\n                try {\n                    hook.join();\n                    break;\n                } catch (InterruptedException ignored) {\n                }\n            }\n        }\n    }<\/code><\/pre>\n<p>\u6267\u884crunHooks\u7684\u65f6\u5019\uff0c\u4f1a\u542f\u52a8\u6240\u6709\u7684hook\u7ebf\u7a0b\uff0c\u4ec0\u4e48\u65f6\u5019\u8c03\u7528runHooks\u65b9\u6cd5\u7684\u5462\uff1f<\/p>\n<h4><strong>2.3 \u6267\u884c\u65f6\u673a<\/strong><\/h4>\n<p>\u4e3a\u4ec0\u4e48\u5728\u7cfb\u7edf\u9000\u51fa\u7684\u65f6\u5019\u4f1a\u6267\u884c\u6dfb\u52a0\u7684hook\u5462\uff1f\u6211\u4eec\u770b\u4e00\u4e0b\u6b63\u5e38\u7684\u9000\u51fa\u64cd\u4f5cSystem#exit\u65b9\u6cd5\u3002<\/p>\n<h5><strong>1\uff09 \u7c7b\u8c03\u7528\u5c42\u7ea7<\/strong><\/h5>\n<p>System-&gt;Runtime-&gt;Shutdown-&gt;ApplicationShutdownHooks<\/p>\n<h5><strong>2\uff09 \u65b9\u6cd5\u8c03\u7528<\/strong><\/h5>\n<p>\u7cfb\u7edf\u9000\u51fa\u5165\u53e3\uff1aSystem#exit<\/p>\n<p>\u6b65\u9aa4 1&#8211;&gt;System#exit<\/p>\n<p>\u6b65\u9aa4 2&#8211;&gt;Runtime#exit;<\/p>\n<p>\u6b65\u9aa4 3&#8211;&gt; Shutdown#<em>exit<\/em><\/p>\n<p><strong>\u6b65\u9aa4 4&#8211;&gt; Shutdown#runHooks<\/strong><\/p>\n<p><strong>\u6b65\u9aa4 5&#8211;&gt; ApplicationShutdownHooks#runHooks<\/strong><\/p>\n<p>\u6b65\u9aa4 6&#8211;&gt;\u542f\u52a8\u6dfb\u52a0\u7684hook\u7ebf\u7a0b<\/p>\n<h5><strong>3\uff09 \u8865\u5145\u4e00\u4e0b<\/strong><\/h5>\n<p><strong>\u4e3a\u4ec0\u4e48\u6b65\u9aa44\u4f1a\u8c03\u7528\u5230\u6b65\u9aa45\u5462\uff1f<\/strong><\/p>\n<p>\u53ef\u4ee5\u770b\u4e00\u4e0bApplicationShutdownHooks\u7684\u6784\u9020\u51fd\u6570\uff0c\u5728\u521b\u5efa\u7684\u65f6\u5019\uff0c\u5c01\u88c5\u4e86runHooks\u65b9\u6cd5\uff0c\u653e\u5230\u4e86Shutdown\u7684\u94a9\u5b50\u96c6\u5408\u91cc\u3002<\/p>\n<p>\u5982\u6b64\u5f62\u6210<strong>\u95ed\u73af<\/strong>\uff0c\u5728\u7cfb\u7edf\u6b63\u5e38\u9000\u51fa\u7684\u65f6\u5019\uff0c\u6700\u7ec8\u6267\u884c\u6211\u4eec\u6dfb\u52a0\u7684hook\u3002<\/p>\n<h2><strong>\u4e09\u3001\u4e3e\u4e2a\u4f8b\u5b50<\/strong><\/h2>\n<p>\u4e86\u89e3\u4e86\u57fa\u672c\u539f\u7406\uff0c\u6211\u4eec\u770b\u4e00\u4e0b\u600e\u4e48\u4f7f\u7528\u7684<\/p>\n<pre><code>    public static void main(String[] args) throws InterruptedException {\n        Thread thread = new Thread() {\n            @Override\n            public void run() {\n                System.out.println(&quot;\u7b49\u7b49\u6211&quot;);\n            }\n        };\n        Runtime.getRuntime().addShutdownHook(thread);\n        System.out.println(&quot;\u7a0b\u5e8f\u5173\u95ed&quot;); \n   }\n    \u8f93\u51fa\uff1a\n    \u7a0b\u5e8f\u5173\u95ed\n    \u7b49\u7b49\u6211<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u5728JVM\u9000\u51fa\u7684\u65f6\u5019\u8c03\u7528\uff0c\u6267\u884c\u4e86\u6b64\u7ebf\u7a0b\uff0c\u6211\u4eec\u5f00\u53d1\u4e2d\uff0c\u54ea\u4e9b\u573a\u666f\u53ef\u4ee5\u4f7f\u7528\u5462\uff1f<\/p>\n<h2><strong>\u56db\u3001\u5e94\u7528\u573a\u666f<\/strong><\/h2>\n<p>\u5173\u95ed\u94fe\u63a5\u3001\u7ebf\u7a0b\u3001\u8d44\u6e90\u91ca\u653e\u3001\u8bb0\u5f55\u6267\u884c\u72b6\u6001\u7b49\u3002<\/p>\n<h2><strong>\u4e94\u3001\u98ce\u9669\u70b9<\/strong><\/h2>\n<h3>1\u3001\u957f\u65f6\u95f4\u7b49\u5f85<\/h3>\n<p>\u5982\u679c\u6dfb\u52a0\u7684hook\u7ebf\u7a0b\u957f\u65f6\u95f4\u6267\u884c\uff0c\u6211\u4eec\u7684\u9000\u51fa\u547d\u4ee4\u4f1a\u4e00\u76f4\u7b49\u5f85\uff0c\u4e3a\u4ec0\u4e48\u5462\uff1f<\/p>\n<p>\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u6211\u4eec\u5728\u6267\u884c\u7684\u65f6\u5019sleep\u4e00\u4e0b<\/p>\n<pre><code>  public static void main(String[] args) throws InterruptedException {\n        Thread thread = new Thread() {\n            @Override\n            public void run() {\n                try {\n                    Thread.sleep(1000*300);\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n                System.out.println(new Date()+&quot; \u7b49\u62115\u5206\u949f&quot;);\n            }\n        };\n        Runtime.getRuntime().addShutdownHook(thread);\n        System.out.println(new Date()+&quot; \u7a0b\u5e8f\u5173\u95ed&quot;);\n    }\n\u8f93\u51fa\uff1a\nTue Nov 12 17:37:38 CST 2024 \u7a0b\u5e8f\u5173\u95ed\nTue Nov 12 17:42:38 CST 2024 \u7b49\u62115\u5206\u949f<\/code><\/pre>\n<h3>2\u3001\u539f\u56e0<\/h3>\n<p>JVM\u5728\u9000\u51fa\u7684\u65f6\u5019\u4f1a\u8c03\u7528runHooks\u65b9\u6cd5\uff0c\u770b\u4e00\u4e0b\u4e0a\u9762\u7684\u65b9\u6cd5java.lang.ApplicationShutdownHooks#<strong>runHooks<\/strong>\u65b9\u6cd5\u3002<\/p>\n<p>\u5173\u952e\u5b57 <strong>hook.join();<\/strong> \u4e3b\u7ebf\u7a0b\u4f1a\u7b49\u5f85\u5b50\u7ebf\u7a0b\u6267\u884c\u5b8c\u6210\u3002<\/p>\n<p>\u5982\u679c\u7a0b\u5e8f\u4e00\u76f4\u6267\u884c\uff0c\u4e0d\u80fd\u9000\u51fa\u600e\u4e48\u529e\uff1f<\/p>\n<h3>3\u3001\u89e3\u51b3\u65b9\u6848<\/h3>\n<p>1 ) \u5199\u4ee3\u7801\u65f6\u5019\u63a7\u5236\u6267\u884c\u903b\u8f91\u3001\u65f6\u957f<\/p>\n<p>2) kill -9 \u547d\u4ee4 \u5f3a\u5236\u9000\u51fa<\/p>\n<h2><strong>\u516d\u3001\u6269\u5c55<\/strong><\/h2>\n<p>1\u3001Runtime.getRuntime#<strong>addShutdownHook<\/strong>\u662f\u9762\u5411\u5f00\u53d1\u8005\u7684<\/p>\n<p>ApplicationShutdownHook#<strong>add<\/strong>\u3001Shutdown#<strong>add<\/strong>\u6211\u4eec\u90fd\u4e0d\u80fd\u76f4\u63a5\u4f7f\u7528\u3002<\/p>\n<p>2\u3001\u8bb8\u591a\u4e2d\u95f4\u4ef6\u6846\u67b6\u4e5f\u5229\u7528addShutdownHook\u6765\u5b9e\u73b0\u8d44\u6e90\u56de\u6536\u3001\u6e05\u7406\u7b49\u64cd\u4f5c<\/p>\n<p>\u6bd4\u5982Spring\u6846\u67b6\u4e2d\uff0c\u4f7f\u7528\u4e86ShutdownHook\u6ce8\u518c\uff0c\u6211\u4eec\u5e38\u7528\u7684@PreDestroy\u5728Bean\u9500\u6bc1\u524d\u6267\u884c\u4e00\u4e9b\u64cd\u4f5c\uff0c\u4e5f\u662f\u501f\u52a9\u5176\u56de\u8c03\u7684\u3002<\/p>\n<h2><strong>\u4e03\u3001\u603b\u7ed3<\/strong><\/h2>\n<p>1\u3001\u672c\u6587\u7b80\u5355\u4ecb\u7ecd\u4e86\u4e00\u4e0bShutdownHook\u4f7f\u7528\u3001\u539f\u7406\u3001\u98ce\u9669\u70b9\u3002<\/p>\n<p>2\u3001\u6211\u4eec\u5de5\u4f5c\u4e2d\u53ef\u4ee5\u81ea\u5df1\u6ce8\u518cShutdownHook\uff0c\u4e3b\u52a8\u91ca\u653e\u4e00\u4e9b\u8d44\u6e90\uff0c\u964d\u4f4e\u98ce\u9669\u3002<\/p>\n<p>3\u3001\u5c0f\u77e5\u8bc6\u5206\u4eab\uff0c\u4e0d\u8db3\u4e4b\u5904\u6b22\u8fce\u5927\u5bb6\u6307\u6b63\uff0c\u5173\u4e8ejava\u91cc\u7684\u77e5\u8bc6\u70b9\u4e5f\u6b22\u8fce\u5927\u5bb6\u8ba8\u8bba\u5206\u4eab\u3002<\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000047357506\">https:\/\/segmentfault.com\/a\/1190000047357506<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4e00\u3001\u5148\u63d0\u51fa\u4e00\u4e2a\u95ee\u9898 \u6211\u4eec\u5982\u679c\u5728JVM\u9000\u51fa\u7684\u65f6\u5019\u505a\u4e00\u4e9b\u4e8b\u60c5\uff0c\u6bd4\u5982\u5173\u95ed\u8fdc\u7a0b\u94fe\u63a5\uff0c\u600e\u4e48\u5b9e\u73b0\u5462\uff1f \u4e8c\u3001Shutdown [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10021058","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10021058","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10021058"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10021058\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10021058"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10021058"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10021058"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}