我在Java中有一个相当复杂的关闭 - 有很多清理工作要做。特别是我试图找出如何从关闭钩子线程错误处理。我的代码目前包括:
try {
return shutdownPromise = doShutdown();
}
catch (Throwable exc) {
logger.error("An exception was thrown while shutting down the application.", exc);
System.exit(1);
return null;
}
当我最初写这篇文章时,我基本上认为,关机时的错误应该直接转到exit
。但是exit
并不是那么低级别;它调用了shutdown hooks。
所以我想 -
答案 0 :(得分:20)
首先,简单的答案是:你的进程陷入僵局。
System.exit结束调用Shutdown.exit
,以this code block结尾:
synchronized (Shutdown.class) {
/* Synchronize on the class object, causing any other thread
* that attempts to initiate shutdown to stall indefinitely
*/
sequence();
halt(status);
}
评论完全准确。但要理解这一点,我们需要确切了解关闭钩子的作用。
按this answer here中的说明,通过ApplicationShutdownHooks.add
添加了关机挂钩。请注意,上面的sequence
方法最终会在Shutdown.runHooks
中的this line of code结束:
if (hook != null) hook.run();
首先,请注意这些挂钩不您的应用程序关闭挂钩。它们是系统关闭挂钩,它们是不同的,其中一个负责确保应用程序关闭挂钩运行。请注意,运行,而不是开始。换句话说,它阻止。其中一个关闭挂钩将是一个系统挂钩,它同时启动所有应用程序关闭挂钩(您可以为自己或链接的答案跟踪此代码),然后阻塞,直到它们都使用Thread.join
调用完成。其中一个将是你的应用程序关闭钩子 - 如果它调用System.exit
,它将等待永久锁定Shutdown.class
。
接下来,愚蠢的回答:改为呼叫Runtime.getRuntime().halt()
。我说“愚蠢的答案”,因为这可能是你想要做的稍微低一点的事情,而不是退出。如果System.exit
代表一个失败的干净关闭,那么halt
是一个硬关闭,它将永远立即成功。
接下来,更聪明的回答:可能没什么。只需让你的关机挂钩完成,原因如下。您的关闭挂钩不拥有关闭 - 特别是,可能还有其他需要执行其工作的关闭挂钩。相反,我怀疑这个钩子的责任之一是最终迫使硬关机。我建议立即将其创建为延迟任务,然后将此钩子正常填写。