13

我在 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不是那么低的水平;它调用关闭挂钩。

所以我认为 -

  1. 从关闭挂钩调用退出有什么作用?
  2. 从关闭挂钩错误处理的正确方法是什么?
4

1 回答 1

23

首先,简单的答案:您的进程死锁。

System.exit 结束调用Shutdown.exit,以这个代码块结束:

synchronized (Shutdown.class) {
     /* Synchronize on the class object, causing any other thread
      * that attempts to initiate shutdown to stall indefinitely
      */
     sequence();
     halt(status);
}

评论完全准确。但要理解这一点,我们需要确切了解关闭挂钩的作用。

关机钩子是通过添加的ApplicationShutdownHooks.add,正如这里的答案中所解释的那样。请注意,sequence上面的方法最终会在以下代码行中结束Shutdown.runHooks

if (hook != null) hook.run();

Firstly, note these hooks are not your application shutdown hooks. They are system shutdown hooks, which are different, and one of them is responsible for ensuring your application shutdown hooks run. Notice that is run, not start. In other words, it blocks. One of these shutdown hooks will be a system hook that concurrently starts all the application shutdown hooks (you can trace this code for yourself or in linked answer), then blocks until they all complete using a Thread.join call. One of these will be your application shutdown hook - which, if it calls System.exit, will be waiting to get the lock on Shutdown.class forever.

Next, the dumb answer: call Runtime.getRuntime().halt() instead. I say "the dumb answer" because this is probably the slightly lower level thing you were looking to do instead of exit. If System.exit represents a clean shutdown that failed, then halt is a hard shutdown that will always succeed immediately.

Next, the smarter answer: probably nothing. Just let your shutdown hook finish, for the following reasons. Your shutdown hook does not own the shutdown - in particular, there may be other shutdown hooks that need to do their work. Conversely, I suspect one of the responsibilities of this hook is to force a hard shutdown eventually. I would recommend creating that as a delayed task right away then letter this hook complete normally.

于 2013-10-23T21:11:13.737 回答