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