在 Java 中捕获 Ctrl+C

发布于 2024-08-08 21:11:32 字数 77 浏览 3 评论 0原文

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

Is it possible to catch the Ctrl+C signal in a java command-line application? I'd like to clean up some resources before terminating the program.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你怎么敢 2024-08-15 21:11:32

您可以附加 VM 的关闭挂钩,每当 VM 关闭时都会运行该钩子:

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

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

  • 虚拟机因用户中断(例如键入 Ctrl+C)或系统范围事件(例如当用户注销或系统关闭时。

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

此外,正如评论者 Jesper 指出的那样,关闭挂钩保证在 VM 正常关闭时运行,但如果 VM 进程被强制终止,则它们不会运行。如果本机代码出错或者强行终止进程(kill -9taskkill /f),则可能会发生这种情况。

但在这些情况下,无论如何,所有的赌注都会被取消,所以我不会在这上面浪费太多的想法。

You can attach a shutdown hook to the VM which gets run whenever the VM shuts down:

The Java virtual machine shuts down in response to two kinds of events:

  • The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or

  • The virtual machine is terminated in response to a user interrupt, such as typing Ctrl+C, or a system-wide event, such as user logoff or system shutdown.

The thread you pass as shutdown hook has to follow several rules, though, so read the linked documentation carefully to avoid any problems. This includes ensuring thread-safety, quick termination of the thread, etc.

Also, as commenter Jesper points out, shutdown hooks are guaranteed to run on normal shutdown of the VM but if the VM process is terminated forcibly they don't. This can happen if native code screws up or if you forcibly kill the process (kill -9, taskkill /f).

But in those scenarios all bets are off anyway, so I wouldn't waste too much thought on it.

ˇ宁静的妩媚 2024-08-15 21:11:32

只是为了快速控制台测试目的......

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();
            }
        }
    });

Just for quick console testing purposes...

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();
            }
        }
    });
肤浅与狂妄 2024-08-15 21:11:32

最上面的答案建议使用关闭挂钩。关闭钩子带来的麻烦远远超过其价值。它们以不确定的顺序运行,并且您所依赖的库可能会添加自己的关闭挂钩,这可能意味着您自己的关闭挂钩所依赖的某些内容可能会在您的关闭挂钩运行之前被取消初始化。避免让自己头痛,并使用信号处理程序:

Signal.handle(new Signal("INT"),  // SIGINT
    signal -> System.out.println("Interrupted by Ctrl+C"));

Signal 目前是 sun.misc.Signal,这意味着它将被弃用 - 但它被替换为当前名为 jdk.internal.misc.Signal,因此在 Java 团队弄清楚如何以非内部方式公开公开信号处理程序之前,请注意此调用可能会消失。但目前(从 JDK 11 开始),sun.misc.Signal 仍然存在。

The top answer suggests using a shutdown hook. Shutdown hooks are far more trouble than they are worth. They run in an indeterminate order, and libraries you depend upon may add their own shutdown hooks, which may mean that something your own shutdown hook depends upon may be de-initialized before your shutdown hook runs. Save yourself the headache, and use a signal handler:

Signal.handle(new Signal("INT"),  // SIGINT
    signal -> System.out.println("Interrupted by Ctrl+C"));

Signal is currently sun.misc.Signal, which means it will be deprecated -- but what it's being replaced with is currently named jdk.internal.misc.Signal, so until the Java team figure out how to publicly expose signal handlers in a non-internal way, beware that this call may go away. For now though (as of JDK 11), sun.misc.Signal still exists.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文