简体   繁体   中英

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.

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:

// 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:

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:

  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.
  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).
  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.
  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?!
  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.

Any idea what is going on with the Swing event loop here? I'm stumped... Are there things that will cause the Swing event loop to terminate early (scenario 2 and 3)? Do multi-threaded applications prevent Swing from detecting the last disposed window (scenario 4)?

For reference, here is the source of the Google AppEngine Dev Server .

Items #4 and #5 are actually expected behavior. A Java/Swing application doesn't stop when the last Swing window is disposed, but when the last thread stops executing. 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. 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; (due to #4)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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