在Java中捕捉Ctrl + C


79

是否可以在Java命令行应用程序中捕获Ctrl+C信号?我想在终止程序之前清理一些资源。

Answers:


88

您可以将关闭挂钩连接到VM,只要VM关闭,该挂钩便会运行:

Java虚拟机响应以下两种事件而关闭:

  • 当最后一个非守护程序线程退出时,或者调用exit(等效于System.exit)方法时,程序将正常退出,或者

  • 响应于用户中断(例如键入Ctrl+ C)或系统范围的事件(例如用户注销或系统关闭)来终止虚拟机。

但是,您作为关闭挂钩传递的线程必须遵循多个规则,因此请仔细阅读链接的文档,以避免出现任何问题。这包括确保线程安全,线程的快速终止等。

另外,正如评论者Jesper指出的那样,可以确保关闭挂钩在VM正常关闭时运行,但是如果VM进程被强行终止,则不会。如果本机代码搞砸了,或者您强行终止了该进程()kill -9,则可能会发生这种情况taskkill /f

但是在那种情况下,所有的赌注都没有,所以我不会在此浪费太多的思考。


1
注意,不能保证在所有情况下都可以运行关闭挂钩。在某些情况下,它们可能无法运行,因此请不要根据关闭挂钩中的操作来使程序正确运行。
杰斯珀,

4
当进程被强制终止(TerminateProcess()SIGKILL)但不在正常操作范围内时,它们不会运行,并且由于Ctrl + C已被关闭钩子覆盖,因此可以安全地使用它。如果操作系统实际上终止了您的进程,您将无能为力。
乔伊(Joey)

1
kill -HUP是Unix上最“软”的命令,应运行shutdown钩子。不确定默认值kill
livefree75

1
默认终止会导致关闭挂钩在我的机器上运行(Redhat 7.3)。杀-9没有。
MikeKulls

2
不能保证关机挂钩以任何特定的顺序运行,因此,如果关机挂钩依赖于尚未运行的其他关机挂钩(反之亦然),则可能会遇到问题。
卢克·哈奇森

27

仅用于快速控制台测试目的...

Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            try {
                Thread.sleep(200);
                System.out.println("Shutting down ...");
                //some cleaning up code...

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
        }
    });
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.