如何确保在退出java应用程序之前运行一段代码



我使用的是一个授权的API,它有一种方法可以从拥有有限许可证的许可证服务器获取/释放许可证对象。在我的应用程序开始时,我调用该方法来获取许可证,但我希望确保即使我的程序突然终止/崩溃(异常、SIGTERM等),也能释放该方法。关机挂钩是解决这个问题的最佳方式吗?

@thedan关于硬JVM崩溃的说法是正确的。如果JVM严重崩溃或得到SIGKILL,那么它在退出之前将没有机会运行任何东西。在这种情况下,您无法在Java中对此进行补救。(但其他语言的情况也一样…)

但是,如果JVM响应所有非dameon线程的结束而有序关闭,调用System.exit(),获取SIGINT等等,那么JVM将尝试运行关闭挂钩。在Q&一个页面和javadocs。

finally方法也是一种选择,但只有当有问题的线程在JVM退出之前终止时才有效。如果调用System.exit()或JVM被信号终止,则不会发生这种情况。关机挂钩适用于更多情况。

(在我看来,finally实际上是用于在单个线程上执行清理,而不是用于整个应用程序。但是,如果您的应用程序仅由一个线程组成……或者如果它有一个负责有序关闭的主线程……那么finally可以用于应用程序清理。)


真正的解决方案是配置授权的API,以便许可证管理器可以在不释放许可证的情况下检测使用许可证的应用程序实例何时离开。这是否可能取决于许可证管理者。

如果程序因JVM崩溃而终止,则不能依赖于所调用的任何东西。

如果程序因不涉及JVM的异常而终止,那么您应该能够将所有内容封装在try/catch/finally块中。finally块中的任何代码都将保证在代码退出之前运行。

对于例外情况,您可以将main的主体包裹在try/catch/block中。为了处理SIGTERM信号,您可以添加一个关机挂钩。但是,不能保证关机挂钩会被SIGKILL这样的信号触发。

来自Java文档:

在极少数情况下,虚拟机可能会中止,即停止运行时没有干净地关闭。当虚拟机器在外部终止,例如使用SIGKILL信号Unix上的CCD_ 10调用。虚拟如果本机方法出现错误,损坏内部数据结构或试图访问不存在的记忆如果虚拟机中止,则无法保证可以确定是否将运行任何关闭挂钩

您可以通过从不调用Sytem.exit()来实现这一点。在main()中,您可以使用创建"最后一道防线">

try {
startApp();
} catch (Exception ex) {
// do some logging
} finally {
releaseLicense();
}

相关内容

最新更新