简体   繁体   English

Java Swing应用程序意外终止

[英]Java Swing application terminates unexpectedly

I'm trying to write a Swing application in Java that also runs the Google AppEngine Dev-Server (see Developing a Java Application that uses an AppEngine database ) and am running into a strange problem with the Swing Eventloop. 我正在尝试用Java编写一个Swing应用程序,该应用程序还运行Google AppEngine Dev-Server(请参阅开发使用AppEngine数据库的Java应用程序 ),并且遇到了Swing Eventloop的一个奇怪问题。

I have the following two classes: 我有以下两个类:

A debug-window, which will eventually receive log messages, etc: 一个调试窗口,它最终会收到日志消息等:

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

A helper-class that loads the Google AppEngine Dev-Server: 加载Google AppEngine Dev-Server的帮助程序类:

// 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.");
    }
}

My main(...) method looks like this: 我的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
        }
    });
}

With this I'm getting some very strange behavior regarding the Swing Eventloop: 有了这个,我对Swing Eventloop有一些非常奇怪的行为:

  1. First, the way Swing should work: If I comment out the line DevServer.launch(...) in main(...) , the application launches, shows the debug window, keeps running, and when I close the debug window, it shuts down. 首先,Swing的工作方式:如果我在main(...) DevServer.launch(...)行,应用程序启动,显示调试窗口,继续运行,当我关闭调试窗口时,它关闭了。
  2. If I add DevServer.launch(...) back in, it launches the server as expected, and then quits immediately (it probably also showed the debug window briefly, but it's too quick to see). 如果我重新添加DevServer.launch(...) ,它会按预期启动服务器,然后立即退出(它可能还会短暂显示调试窗口,但它太快看不到)。
  3. If I move DevServer.launch(...) line after SwingUtilities.invokeLater(...) , it shows the debug window, then launches the server, and when the server is up, it quits immediately. 如果我在SwingUtilities.invokeLater(...)之后移动DevServer.launch(...)行,它会显示调试窗口,然后启动服务器,当服务器启动时,它会立即退出。
  4. Now it get's really weird: If I change the line to DevServer.launch(args, false) , ie I don't wait for the server to actually launch, but simply let my main(...) method complete immediately, the debug window shows, the server loads correctly, the application keeps running, but doesn't quit if I close the debug window?! 现在它变得非常奇怪:如果我将行更改为DevServer.launch(args, false) ,即我不等待服务器实际启动,而只是让我的main(...)方法立即完成,调试窗口显示,服务器正确加载,应用程序继续运行,但是如果我关闭调试窗口则不退出?!
  5. If I then also change JFrame.DISPOSE_ON_CLOSE to JFrame.EXIT_ON_CLOSE , the debug window shows, the server loads correctly, the application keeps running, and it quits correctly if I close the debug window. 如果我还将JFrame.DISPOSE_ON_CLOSE更改为JFrame.EXIT_ON_CLOSE ,则调试窗口显示,服务器正确加载,应用程序继续运行,如果我关闭调试窗口,它将正确退出。

Any idea what is going on with the Swing event loop here? 知道Swing事件循环在这里发生了什么吗? I'm stumped... Are there things that will cause the Swing event loop to terminate early (scenario 2 and 3)? 我很难过......有什么东西会导致Swing事件循环提前终止(场景2和3)? Do multi-threaded applications prevent Swing from detecting the last disposed window (scenario 4)? 多线程应用程序是否阻止Swing检测到最后处理的窗口(方案4)?

For reference, here is the source of the Google AppEngine Dev Server . 作为参考,以下是Google AppEngine Dev Server的来源

Items #4 and #5 are actually expected behavior. 项目#4和#5实际上是预期的行为。 A Java/Swing application doesn't stop when the last Swing window is disposed, but when the last thread stops executing. 当放置最后一个Swing窗口时,Java / Swing应用程序不会停止,但是当最后一个线程停止执行时。 These two conditions are equivalent for single-threaded applications, but not for multi-threaded ones. 这两个条件对于单线程应用程序是等效的,但对于多线程应用程序则不是。

As for #1, #2 and #3: looking through the AppEngine Dev Server code, I noticed a fair amount of System.exit(int) calls in there. 至于#1,#2和#3:通过AppEngine Dev Server代码查看,我注意到有相当数量的System.exit(int)调用。 One of these is probably the culprit. 其中一个可能是罪魁祸首。 If the code you're showing is all that's relevant, then the offending System.exit is likely called in response to the connection established after if (!waitFor) return; 如果您显示的代码是相关的,那么可能会调用违反的System.exit以响应if (!waitFor) return;后建立的连接if (!waitFor) return; (due to #4) (由于#4)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM