4

Google AppEngine Dev-Server も実行する Java で Swing アプリケーションを作成しようとしています (「AppEngine データベースを使用する Java アプリケーションの開発」を参照)。Swing Eventloop で奇妙な問題が発生しています。

次の2つのクラスがあります。

最終的にログメッセージなどを受け取るデバッグウィンドウ:

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

私の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. DevServer.launch(...)まず、Swing の動作方法: の行をコメント アウトするmain(...)と、アプリケーションが起動し、デバッグ ウィンドウが表示され、実行が継続されます。デバッグ ウィンドウを閉じると、アプリケーションはシャットダウンします。
  2. もう一度追加するDevServer.launch(...)と、期待どおりにサーバーが起動し、すぐに終了します (デバッグ ウィンドウも短時間表示された可能性がありますが、表示が速すぎます)。
  3. DevServer.launch(...)の後に行を移動するSwingUtilities.invokeLater(...)と、デバッグ ウィンドウが表示され、サーバーが起動し、サーバーが起動するとすぐに終了します。
  4. ここで、非常に奇妙になります: 行を に変更するとDevServer.launch(args, false)、つまり、サーバーが実際に起動するのを待たずにmain(...)メソッドをただちに完了すると、デバッグ ウィンドウが表示され、サーバーは正しく読み込まれ、アプリケーションは実行され続けますが、デバッグウィンドウを閉じても終了しない?!
  5. 次に にも変更JFrame.DISPOSE_ON_CLOSEするJFrame.EXIT_ON_CLOSEと、デバッグ ウィンドウが表示され、サーバーが正しく読み込まれ、アプリケーションが実行され続け、デバッグ ウィンドウを閉じると正しく終了します。

ここで、Swing イベント ループで何が起こっているのか分かりますか? 困惑しています... Swing イベント ループが早期に終了する原因となるものはありますか (シナリオ 2 および 3)? マルチスレッド アプリケーションは、Swing が最後に破棄されたウィンドウを検出するのを妨げますか (シナリオ 4)?

参考までに、Google AppEngine Dev Server のソースを次に示します

4

1 に答える 1

1

項目 4 と 5 は、実際には予想される動作です。Java/Swing アプリケーションは、最後の Swing ウィンドウが破棄されたときに停止するのではなく、最後のスレッドの実行が停止したときに停止します。これら 2 つの条件は、シングルスレッド アプリケーションでは同等ですが、マルチスレッド アプリケーションでは同等ではありません。

#1、#2、および #3 について: AppEngine Dev Server コードを調べたところ、かなりの量のSystem.exit(int)呼び出しが含まれていることに気付きました。これらのうちの1つがおそらく犯人です。表示しているコードが関連するすべての場合、(#4 により)System.exit後に確立された接続に応答して問題が呼び出される可能性があります。if (!waitFor) return;

于 2013-07-20T09:31:38.403 に答える