如果从关闭挂钩调用 System.exit 会发生什么?

2023-12-25

我在 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. But exit水平并没有那么低;它调用关闭挂钩。

所以我认为 -

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

首先,简单的答案:您的流程陷入僵局。

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是一种总是会立即成功的硬关闭。

接下来,更聪明的答案是:可能什么也没有。出于以下原因,只需让关闭挂钩完成即可。您的关闭挂钩不拥有关闭功能 - 特别是,可能还有其他关闭挂钩需要完成其工作。相反,我怀疑这个钩子的职责之一是最终强制硬关闭。我建议立即将其创建为延迟任务,然后让该钩子正常完成。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果从关闭挂钩调用 System.exit 会发生什么? 的相关文章

随机推荐