如何在Java中优雅地处理SIGKILL信号

8 浏览
0 Comments

如何在Java中优雅地处理SIGKILL信号

当程序收到终止信号时,您如何处理清理工作?例如,有一个我连接的应用程序希望任何第三方应用程序(我的应用程序)在注销时发送一个finish命令。当我的应用程序被kill -9销毁时,最好的方式是如何发送该finish命令?

编辑1:无法捕获kill -9。谢谢大家纠正我。

编辑2:我想这种情况下就是调用kill,与按下Ctrl-C键相同。

0
0 Comments

在Java中优雅处理SIGKILL信号的问题是由于以下原因引起的:Java虚拟机(JVM)使用SIGKILL信号作为正常终止的一种方式,因此无法通过常规方式处理该信号。

然而,有一些方法可以在某些JVM中处理自定义信号。例如,可以使用Sun内部的"sun.misc.Signal.handle(Signal, SignalHandler)"方法调用来注册信号处理程序,但可能无法用于JVM使用的信号(如INT或TERM信号)。

要能够处理任何信号,需要跳出JVM并进入操作系统领域。

我通常的做法是在Perl脚本中启动JVM,并使用"waitpid"系统调用让脚本等待JVM。这样,无论JVM以何种方式退出,我都会收到通知,并可以采取相应的操作。

值得注意的是,可以使用"sun.misc.Signal"捕获INT和TERM信号,但无法处理QUIT信号,因为JVM将其保留用于调试,也无法处理KILL信号,因为操作系统会立即终止JVM。尝试处理这两个信号将引发IllegalArgumentException异常。

0
0 Comments

在Java中,无法优雅地处理SIGKILL信号。这是因为要确保始终可以终止程序,即使程序存在错误或恶意行为。但是SIGKILL并不是终止程序的唯一方法,另一种方法是使用SIGTERM信号。程序可以处理该信号。程序应该通过进行控制但快速的关闭来处理该信号。当计算机关闭时,关闭过程的最后阶段会向每个剩余的进程发送一个SIGTERM信号,给这些进程几秒钟的宽限时间,然后发送一个SIGKILL信号。

处理除了kill -9之外的任何终止信号的方法是注册一个关闭钩子(shutdown hook)。如果使用SIGTERM(kill -15),关闭钩子将起作用。SIGINT(kill -2)确实会导致程序优雅退出并运行关闭钩子。

尝试在OSX 10.6.3和kill -9上运行以下测试程序时,关闭钩子没有运行,这是预期的。在kill -15上,每次都会运行关闭钩子。

public class TestShutdownHook {
    public static void main(String[] args) throws InterruptedException {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                System.out.println("Shutdown hook ran!");
            }
        });
        while (true) {
            Thread.sleep(1000);
        }
    }
}

在任何程序中,实际上没有办法优雅地处理kill -9。

唯一处理kill -9的真正选项是使用另一个监视程序来监视主程序是否消失,或者使用一个包装脚本。可以使用一个Shell脚本来实现这一点,该脚本通过轮询ps命令查找程序列表中的程序,并在其消失时执行相应操作。

#!/usr/bin/env bash
java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"

0