首先,简单的答案:您的流程陷入僵局。
System.exit 结束调用Shutdown.exit
,以这段代码块 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/lang/Shutdown.java#Shutdown.exit%28int%29:
synchronized (Shutdown.class) {
/* Synchronize on the class object, causing any other thread
* that attempts to initiate shutdown to stall indefinitely
*/
sequence();
halt(status);
}
该评论是完全准确的。但为了理解这一点,我们需要确切地了解 shutdown 挂钩的作用。
关闭挂钩通过添加ApplicationShutdownHooks.add
,如中所解释的这个答案在这里 https://stackoverflow.com/a/19550623/1339987。请注意,sequence
上面的方法最终结束这行代码 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/lang/Shutdown.java#Shutdown.runHooks%28%29 in Shutdown.runHooks
:
if (hook != null) hook.run();
首先,请注意这些钩子是not您的应用程序关闭挂钩。它们是系统关闭挂钩,它们是不同的,其中之一负责确保您的应用程序关闭挂钩运行。请注意,这是run, not start。换句话说,它blocks。这些关闭挂钩之一将是一个系统挂钩,它同时启动所有应用程序关闭挂钩(您可以自己跟踪此代码或在链接的答案中跟踪此代码),然后阻塞,直到它们全部使用Thread.join
称呼。其中之一是您的应用程序关闭挂钩 - 如果它调用System.exit
,将等待锁定Shutdown.class
永远。
接下来,愚蠢的答案:打电话Runtime.getRuntime().halt()
反而。我说“愚蠢的答案”是因为这可能是您想要做的稍微低级的事情而不是退出。如果System.exit
代表失败的干净关闭,然后halt
是一种总是会立即成功的硬关闭。
接下来,更聪明的答案是:可能什么也没有。出于以下原因,只需让关闭挂钩完成即可。您的关闭挂钩不拥有关闭功能 - 特别是,可能还有其他关闭挂钩需要完成其工作。相反,我怀疑这个钩子的职责之一是最终强制硬关闭。我建议立即将其创建为延迟任务,然后让该钩子正常完成。