调试JNLP启动的应用程序

9
我创建了一个使用Swing的Java桌面应用程序,并尝试通过使用JNLP从网络启动它。当我从终端启动应用程序时,它可以正常工作,但是一旦我从JNLP启动它,它就无法关闭。每次都必须手动终止进程。
我阅读到如果我的JFrame使用DISPOSE_ON_CLOSE作为默认关闭操作,则可能会出现问题,但实际上并没有。它使用DO_NOTHING_ON_CLOSE(隐式)。此外,在释放所有对象后,我明确调用System.exit(0)。
f = new JFrame("Pacman");
f.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(WindowEvent e) {
        // Terminate the Game-loop:
        GameLoop.INSTANCE.stopLoop();
        // Close the application:
        System.exit(0);
    }
});

我猜关闭应用程序时可能会抛出异常,但我找不到一种方法来获取使用JNLP启动的运行中应用程序的控制台输出(例如堆栈跟踪)。下面是我尝试过的方法:
  • 使用调试参数启动javaws,并使用jconsole进行连接(可以工作,但我找不到任何异常或控制台输出)。
  • 使用调试参数启动javaws,并将IntelliJ调试器附加到它(也可以工作,但没有给我任何输出)
那么,我该如何使用JNLP启动应用程序并获得输出(写入默认输出和错误流),就像我在普通桌面应用程序中所做的一样?

1
我会这样处理:try { GameLoop.INSTANCE.stopLoop(); } catch(Exception e) { e.printStackTrace(); /* 可以弹出一个JOptionPane进行调试 */ } // 关闭应用程序: System.exit(0); - Andrew Thompson
你能发一下 GameLoop.INSTANCE.stopLoop() 的代码吗?从这个方法的名字来看,我认为可能会调用 wait() 或者 Thread#join() 方法,导致无限等待某些原因。调试这个方法也是一个好主意。 - npe
@npe 我没有使用 Thread 类,而是使用了执行器框架。因此,没有 join()wait() 调用。你可以在这里找到整个类(以及整个项目)链接 - Lukas Knuth
@AndrewThompson 真的没有其他更明智的方法吗?如果应用程序挂起,我不认为它会在同一上下文中生成 JOptionPane - Lukas Knuth
1
“真的没有其他方法吗?”我从未意味着这是唯一的方法。这只是一种“快速而肮脏”的暂停执行方式,在关闭之前。您可以将堆栈跟踪元素转储到选项窗格中。 - Andrew Thompson
请问如何在Java Web Start(JNLP)下调试应用程序? - Manuel Romeiro
3个回答

17

解决方案 #1 - 开启Java控制台并查看异常信息。

您可以通过Java控制面板进行操作。 切换到高级选项卡,在Java控制台中确保选择了显示控制台

然后,运行您的应用程序并监视控制台以查找异常。 修复异常。

解决方案 #2 - 正确地调试正在运行的应用程序。

像这样启动Web Start应用程序(适用于Java 1.6及更高版本):

javaws -verbose -J-Xdebug -J-Xnoagent -J-Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=8123 http://myserver.com/path/to/myapp.jnlp

如果使用早期的Java版本(1.4.2,1.5),请设置环境变量,如下所示:

set JAVAWS_VM_ARGS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=8123"

然后通过以下方式运行应用程序:

javaws http://myserver.com/path/to/myapp.jnlp

当应用程序运行时:

  1. 附加调试器(Eclipse 可以 - 使用 Run => Debug Configurations => Remote Java Application,在 Connection Properties 面板中输入传递给 javaws 的端口号(在本例中为:8123)。
  2. 在你的 windowClosing 方法内设置一个断点。
  3. 尝试关闭你的应用程序 - Eclipse 应该会在断点处停止执行。
  4. Step into GameLoop.INSTANCE.stopLoop() 方法,看它在何时何处挂起。

不要期望在控制台看到解决方案,只需使用调试器逐步执行代码 - 如果应用程序挂起,则会显示出挂起的位置。


很好,我现在有异常了。谢谢! - Lukas Knuth
新版Java是否真的需要Xnoagent选项? - keiki
在使用Solution#2中建议的选项启动javaws后,我的应用程序可以在Java 7中启动,但是在从eclipse启动调试器时,它会出现无法连接到VM的错误。我已经指定了正确的端口号(8123),该端口号用于启动javaws。一个观察结果是,javaws在任务管理器中没有显示为进程,这让我感到惊讶,因为应用程序正在启动。 - user1630693

2

有时候,即使控制台也没有显示任何内容,例如当TLS/SSL握手出现问题(即close_notify或handshake_failure)时。在这些情况下,您需要执行以下操作:

  1. Enable the Java logs and tracing in the Java Control Panel > Advanced. Java Control Panel: logs and tracing

  2. Enable parameters for debugging Java & launching the JNLP, there are two ways you can do it:

    2.a. Download the JNLP file and execute it from command line (the SET command is not required in this particular case).

    set JAVA_TOOL_OPTIONS=-Djavax.net.debug=all
    javaws -wait jnlp.jnlp
    

    2.b. Add arguments (i.e. -Djavax.net.debug=all) for the JVM in the Java Control Panel > Java > View (this is not required in this particular), and launch the JNLP file from browser:

    Java Control Panel: jvm arguments

  3. The logs and traces are located in the log directory from the Java Deployment Home from where I paste these locations:

    a. Windows XP: %HOME%\Application Data\Sun\Java\Deployment

    b. Windows 7/Vista: %APPDATA%\..\LocalLow\Sun\Java\Deployment

    c. Linux/Solaris: %HOME%/.java/deployment


0

这个答案是 npe answer 的替代方案,以启用远程调试(Windows)。

  • 进入控制面板;
  • 点击Java,打开Java控制面板;
  • 在Java控制面板内,进入Java选项卡,然后点击“查看”;
  • 这将打开一个窗口,显示已安装的Java版本。在运行时参数中输入"-Xdebug -Xrunjdwp:transport=dt_socket,address=8123,server=y,suspend=n"(如果您想在应用程序启动时进行调试,请将"suspend"更改为"y",这将使应用程序停止直到编辑器远程连接);

Enabling remote debug

之后,配置您的编辑器以远程调试到已配置的端口(在本例中为localhost:8123)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接