在java中发出运行shutdown hook

时间:2014-01-29 16:00:59

标签: java batch-file logging cmd shutdown-hook

我试图让一个关闭钩子在java中运行。此挂钩的目的是写入程序终止的日志文件。 java应用程序被编译成jar文件并使用批处理文件执行,这意味着应用程序的输出将转到cmd.exe窗口。关闭此cmd窗口时,我希望应用程序记录它已关闭。

该应用程序旨在无限期运行并在特定时间执行某些任务。因此,程序正在“While true”循环中执行一系列检查。我不明白为什么这个钩子不会记录应用程序正在关闭!

在主要方法中我们有:

final Thread mainThread = Thread.currentThread();
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
{
    @Override
    public void run()
    {
        try { mainThread.join(); }
        catch (InterruptedException e) { }
        mission.log("Program Closed.", true);
    }
}
));

所有“任务”都是我的自定义类的一个实例,用于执行数据记录。当你调用方法“log”时,它有一个BufferedWriter,它调用它的.write(),. newLine()和.flush()方法。

当我杀死批处理窗口时,我似乎无法在我的日志文件中获得“程序已关闭”行。我做错了什么?

4 个答案:

答案 0 :(得分:3)

强行终止应用程序,即不正常,因此JVM不知道应用程序正在退出,因此不会调用关闭挂钩。

不幸的是,没有办法(至少在Windows中)提供一种机制来确保始终调用钩子。这只是可以调用的东西,但不能保证。

答案 1 :(得分:0)

在进程退出之前无法始终执行某些操作。例如。如果将插头从墙壁插座中拔出,计算机会立即关闭。或者,如果操作系统通过将其从调度程序中删除CPU时间来杀死该进程,则它也没有机会。

但是,如果删除代码

    try { mainThread.join(); }
    catch (InterruptedException e) { }

然后至少会针对某些情况执行,例如正常终止该过程。在这里检查主线程是没有意义的,因为主线程已经完成其工作(它退出main()方法)执行了shutdown钩子,或者主线程将继续运行直到JVM决定终止(如果从外部终止)。

比较How to gracefully handle the SIGKILL signal in Java的已接受答案,其中包含您尝试做的另一个示例。

答案 2 :(得分:0)

关闭窗口会导致进程终止,因此关闭挂钩将无效。

听起来你根本不想杀死这个过程。您应该考虑使用批处理脚本以外的其他东西。您可以从Windows任务调度程序运行可执行jar并让它一直在后台运行 - 除非有人故意杀死java或发生错误。在这种情况下,您应该尝试捕获异常并以这种方式记录它们。

答案 3 :(得分:0)

这里的每个人都是正确的 - 您无法在程序中记录强制停止。但是,您可以考虑使用另一个程序来“监视”您的程序并等待它退出。然后,“观察者”程序可以记录原始程序的终止,然后退出。