Java Swing 应用程序意外终止

标签 java swing google-app-engine terminate event-loop

我正在尝试用 Java 编写一个 Swing 应用程序,该应用程序还运行 Google AppEngine Dev-Server(请参阅 Developing a Java Application that uses an AppEngine database),但我遇到了 Swing Eventloop 的一个奇怪问题。

我有以下两个类:

一个调试窗口,它最终会接收日志消息等:

public class DebugWindow {

    private static JFrame    debugWindow  = null;
    private static JTextArea debugContent = null;

    public static void show() {
        debugWindow = new JFrame("Debug");
        debugWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        debugContent = new JTextArea("Debug messages go here!");
        debugWindow.add(debugContent, BorderLayout.CENTER);
        debugWindow.pack();
        debugWindow.setVisible(true);
    }
}

加载 Google AppEngine 开发服务器的辅助类:

// other imports
import com.google.appengine.tools.development.DevAppServerMain;

public class DevServer {
    public static void launch(final String[] args, boolean waitFor) {
        Logger logger = Logger.getLogger("");
        logger.info("Launching AppEngine server...");
        Thread server = new Thread() {
            @Override
            public void run() {
                try {
                    DevAppServerMain.main(args);  // run DevAppServer
                } catch (Exception e) { e.printStackTrace(); }
            }
        };
        server.setDaemon(true);  // shut down server when rest of app completes
        server.start();          // run server in separate thread
        if (!waitFor) return;    // done if we don't want to wait for server
        URLConnection cxn;
        try {
            cxn = new URL("http://localhost:8888").openConnection();
        } catch (IOException e) { return; }  // should never happen
        boolean running = false;
        while (!running) {
            try {
                cxn.connect();  // try to connect to server
                running = true;
            } catch (Exception e) {}
        }
        logger.info("Server running.");
    }
}

我的 main(...) 方法如下所示:

public static void main(final String[] args) throws Exception {
    DevServer.launch(args, true);  // launch and wait for AppEngine dev server
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            DebugWindow.show();  // create and show debug window
        }
    });
}

有了这个,我得到了一些关于 Swing Eventloop 的非常奇怪的行为:

  1. 首先,Swing 应该如何工作:如果我注释掉 main(...) 中的 DevServer.launch(...) 行,应用程序将启动, 显示调试窗口,继续运行,当我关闭调试窗口时,它会关闭。
  2. 如果我重新添加 DevServer.launch(...),它会按预期启动服务器,然后立即退出(它可能还会短暂地显示调试窗口,但速度太快了见)。
  3. 如果我在 SwingUtilities.invokeLater(...) 之后移动 DevServer.launch(...) 行,它会显示调试窗口,然后启动服务器,当服务器启动时,它会立即退出。
  4. 现在真的很奇怪:如果我将行更改为 DevServer.launch(args, false),即我不等待服务器实际启动,而只是让我的 main(...) 方法立即完成,调试窗口显示,服务器正确加载,应用程序继续运行,但如果我关闭调试窗口不会退出?!
  5. 如果我随后也将 JFrame.DISPOSE_ON_CLOSE 更改为 JFrame.EXIT_ON_CLOSE,则调试窗口显示,服务器正确加载,应用程序继续运行,如果出现以下情况,它会正确退出我关闭调试窗口。

知道这里的 Swing 事件循环发生了什么吗?我很难过......是否有什么会导致 Swing 事件循环提前终止(场景 2 和 3)?多线程应用程序是否会阻止 Swing 检测最后处理的窗口(场景 4)?

供引用,here is the source of the Google AppEngine Dev Server .

最佳答案

项目 #4 和 #5 实际上是预期的行为。 Java/Swing 应用程序不会在最后一个 Swing 窗口被释放时停止,而是在最后一个线程停止执行时停止。这两个条件对于单线程应用是等价的,但对于多线程应用则不是。

至于 #1、#2 和 #3:查看 AppEngine Dev Server 代码,我注意到其中有相当多的 System.exit(int) 调用。其中之一可能是罪魁祸首。如果您显示的代码都是相关的,那么可能会调用有问题的 System.exit 以响应 if (!waitFor) return; 之后建立的连接(由于 #4)

关于Java Swing 应用程序意外终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17760659/

相关文章:

java - 如何在 Google App Engine 中检测 HTTP 响应大小

java - OpenSAML 仅在 weblogic 上抛出 java.lang.NoClassDefFoundError

java - 运行 3 个线程并在 Java 中等待

java - GraphicsDevice 和 JOptionPane 问题

java - 多线程环境中的 Hibernate.getCurrentSession()

python - GAE中的后台进程

java - 像这样嵌套 try/finally 子句安全吗?

java - 以编程方式检查 .class 文件

java - 客户端停止对服务器的消息使用react

java - 请求线程是否在 http 请求之间重用?