如何让我的 Java 应用程序在 Windows 中正常关闭?

问题描述 投票:0回答:3

我有一个 Java 应用程序,当用户选择“开始”->“关闭”时,我想“很好地”关闭它。我尝试通过 Runtime.addShutdownHook(...) 使用 JVM 关闭侦听器,但这不起作用,因为我无法使用其中的任何 UI 元素。

我还尝试在主应用程序 UI 窗口上使用退出处理程序,但据我所知,它无法暂停或停止关闭。我怎样才能很好地处理关机?

java windows shutdown
3个回答
4
投票

前面提到的 JNI 方法可能会起作用。

您可以使用 JNA,它基本上是 JNI 的包装器,以使其更易于使用。另一个好处是它(至少在我看来)通常比原始 JNI 更快且更易于维护。您可以在 https://jna.dev.java.net/

找到 JNA

如果您只是在开始菜单中启动应用程序,因为您试图使其表现得像 Windows 中的服务,则可以使用此处找到的 java 服务包装器: http://wrapper.tanukisoftware.org/doc/english/download.jsp


4
投票

据我所知,您需要开始使用 JNI 为 Windows WM_QUERYENDSESSION 消息设置消息处理程序。

要执行此操作(如果您像我一样是 Windows 编程新手),您需要使用新的消息处理函数创建一个新的窗口类(如此处所述)并从消息处理程序处理 WM_QUERYENDSESSION。

注意:您需要在消息处理线程上使用 JNIEnv::GetJavaVM(...) ,然后使用 JavaVM::AttachCurrentThread(...) ,然后才能从本机消息处理代码中调用任何 Java 方法。


0
投票

您可以使用

sun.misc.Signal
sun.misc.SignalHandler
内部类将默认的
java.lang.Terminator
替换为您自己的自定义处理程序。不要忘记从那里拨打
System::exit
。 JDK 在内部引发
SIGTERM
来响应
WM_QUERYENDSESSION
。详细信息请参见awt_Toolkit.cpp

public static void setQuitStrategy(Runnable handler) throws Exception {
    Class<?> signalClass = Class.forName("sun.misc.Signal");
    Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");

    Object signal = signalClass.getConstructor(String.class).newInstance("TERM");
    Object signalHandler = Proxy.newProxyInstance(signalHandlerClass.getClassLoader(), new Class[] { signalHandlerClass }, (proxy, method, args) -> {
        handler.run();
        return null;
    });

    Method handle = signalClass.getMethod("handle", new Class[] { signalClass, signalHandlerClass });
    handle.invoke(null, signal, signalHandler);
}
© www.soinside.com 2019 - 2024. All rights reserved.