我正在尝试使用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 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(...)
注释掉行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)?
答案 0 :(得分:1)
第4项和第5项实际上是预期的行为。当放置最后一个Swing窗口时,Java / Swing应用程序不会停止,但是当最后一个线程停止执行时。这两个条件对于单线程应用程序是等效的,但不适用于多线程应用程序。
对于#1,#2和#3:通过AppEngine开发服务器代码查看,我注意到有相当数量的System.exit(int)
次呼叫。其中一个可能是罪魁祸首。如果您显示的代码是相关的,那么可能会在System.exit
(由于#4)之后建立的连接中调用有问题的if (!waitFor) return;