如何让我的Java应用程序在Windows中优雅地关闭?

6

我有一个Java应用程序,当用户选择开始->关闭时,我希望能够'优雅地'关闭它。我尝试过使用JVM关闭监听器通过Runtime.addShutdownHook(...),但由于无法从中使用任何UI元素,因此无法正常工作。

我还尝试在我的主应用程序UI窗口上使用退出处理程序,但据我所知,它没有暂停或停止关闭的方法。如何优雅地处理关闭?


你找到可行的解决方案了吗? - Andrzej Rehmann
3个回答

4
据我所知,您需要开始使用JNI来设置Windows的WM_QUERYENDSESSION消息的消息处理程序。
要做到这一点(如果您像我一样是Windows编程的新手),您需要创建一个新的窗口类和一个新的消息处理函数(如此处所述),并从消息处理程序中处理WM_QUERYENDSESSION。
注:在调用本机消息处理代码中的任何Java方法之前,您需要在消息处理线程上使用JNIEnv :: GetJavaVM(...),然后使用JavaVM :: AttachCurrentThread(...)。

4

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

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

如果你只是在开始菜单中启动应用程序,因为你想让它在Windows中像服务一样运行,你可以使用Java Service Wrapper,它可以在这里找到:http://wrapper.tanukisoftware.org/doc/english/download.jsp


这如何解决在关机过程中需要显示用户界面的问题? - undefined

0
你可以使用sun.misc.Signalsun.misc.SignalHandler内部类来替换默认的java.lang.Terminator,并使用自定义的处理程序。不要忘记从那里调用System::exit。JDK在响应WM_QUERYENDSESSION时内部引发SIGTERM。有关详细信息,请参阅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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接