我试图让一个关闭钩子在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()方法。
当我杀死批处理窗口时,我似乎无法在我的日志文件中获得“程序已关闭”行。我做错了什么?
答案 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)
这里的每个人都是正确的 - 您无法在程序中记录强制停止。但是,您可以考虑使用另一个程序来“监视”您的程序并等待它退出。然后,“观察者”程序可以记录原始程序的终止,然后退出。