如何在Java Web Start(JNLP)下调试应用程序?

50

我知道如何使用Eclipse调试远程Java虚拟机,但我如何对Java Web Start程序进行调试。我在Java Web Start中遇到了一个只出现的问题。这一定与安全有关。

我需要一个适用于当前Java VM(例如1.6.0_12)的解决方案。

10个回答

25

与远程调试其他Java进程的方法类似:您需要为VM设置一些参数(-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=12345 ),然后连接指定的端口。在Java Web Start 6.0中,可以通过使用-J选项来完成此操作,在早期版本中则是通过环境变量JAVAWS_VM_ARGS来完成。详情请参见这里


1
仅供参考:在使用Ubuntu 10.04和12.04以及Webstart 6.0时,只有在设置了server=y参数后才能正常工作。否则,即使端口未被占用,也会出现错误ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510) - Joaquim Oliveira
这个答案对我没用(和另一个答案一样的原因),因为命令javaws会在指定端口上打开调试器,然后启动另一个JVM,它也会尝试做同样的事情。最终结果是“地址已经在使用中”,JVM退出。 - Jason

23

手动启动 JWS VM。这样你可以提供启动参数来打开调试端口。以下是一个描述,步骤如下:

set JAVAWS_TRACE_NATIVE=1
set JAVAWS_VM_ARGS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8989,server=y,suspend=n"
javaws http://server:port/descriptor.jnlp

1
+1 给出色的答案。然而,这个东西不让我编辑它来修复答案中的拼写错误。在“address=8989”之前不应该有空格。 - fool4jesus
@mkoeller在javaws中,http://server:port/descriptor.jnlp应该给出哪个端口号? - Rekha
6
注意,在Windows操作系统中(已在XP上测试),当您设置JAVAWS_VM_ARGS时,必须省略双引号。例如,set JAVAWS_VM_ARGS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8989,server=y,suspend=n - Jaime Hablutzel
在Mac OS X High Sierra上,使用“export”而不是“set”对我有效。 “Export”将变量设置在shell中,并可在其子进程中使用。 - Vincent Gerris
这个答案在我的macOS High Sierra上不起作用。问题似乎是“javaws”命令以调试模式启动(打开端口8989),然后使用新的VM启动我的应用程序,该VM也尝试打开该端口。第二个VM给我错误“地址已在使用中”,然后退出。 - Jason
非常感谢,这对我很有帮助。在Java 8中运行完美(使用批处理文件测试过)。 - aimhaj

16

对于新版本的Java(Java 8u20+和Java 7u70+),我发现像-Xrunjdwp这样的参数不能直接传递,也不能使用JAVAWS_VM_ARGS传递。

消息

Rejecting attempt to specify insecure property: -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000

开始在控制台输出中显示。

唯一有效的解决方案是将这些参数传递到JAVA_TOOL_OPTIONS系统变量中。


1
谢谢你写了这个,你解决了我的问题。在从1.7.0_10移植到1.7.0_75时,需要从JAVAWS_VM_ARGS中删除调试选项并将它们移动到JAVA_TOOL_OPTIONS中。 - Gonen I
这对我也起作用了,我的机器上有几个JDK,所以我从来不知道哪一个会启动 :-| - bakoyaro
3
我尝试过这个,但某种安全检查可能阻止了我的javaws启动(使用JAVA_TOOL_OPTIONS时它无法启动,而不使用则可以启动)。 - Graeme Moss

9
您可以使用-J选项向javaws可执行文件提供debug参数。
示例:
javaws.exe -J-Xdebug -J-Xnoagent -J-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 http://server:port/descriptor.jnlp

4
您需要完成以下步骤:
  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 (optional but useful i.e. problems with tls/ssl handshake as close_notify or handshake_failure) & 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

使用javax.net.debug=all参数,您可以查看握手过程,如果jnlp内部的jar文件是从https连接加载的,则会显示。这种问题很难调试。

...
%% No cached client session
*** ClientHello, TLSv1.2
...
***
... 
Java Web Start Main Thread, received EOFException: error
Java Web Start Main Thread, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Java Web Start Main Thread, SEND TLSv1.2 ALERT:  fatal, description = handshake_failure
Java Web Start Main Thread, WRITE: TLSv1.2 Alert, length = 2
Java Web Start Main Thread, called closeSocket()
#### Java Web Start Error:

1
你混淆了调试和日志/跟踪。 - Horcrux7
@Horcrux7 你说得对。我认为记录日志可以被视为一种调试的方式 :) - lmiguelmh

3

使用Java 8和Windows 10,在命令提示符(cmd.exe)中输入以下内容:

set JAVAWS_TRACE_NATIVE=1
set JAVA_TOOL_OPTIONS=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
javaws java-app.jnlp

在此之后,使用Eclipse(或其他IDE)启动远程Java应用程序调试设置到上述命令中使用的端口(在本例中为8000)。


1
关于在Eclipse中调试.jnlp文件。在Eclipse中,您可以创建一个声明了调试端口的远程Java应用程序。如果您在启动.jnlp应用程序之前启动远程调试应用程序(指向相同的调试端口),则.jnlp应用程序将无法连接到打开的调试端口。解决方案是终止并重新启动调试进程。 - J Slick
@JSlick谢谢你的留言!我更新了我的答案,添加了Eclipse的说明。 - qwertzguy

3

您可以启用调试模式运行JNLP:

javaws -Xnosplash -J-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5009 <application>.jnlp

输出: 正在监听传输 dt_socket 的地址: 5009

使用您喜欢的IDE附加到此,我使用的是IntelliJ IDEA。 运行>附加到进程


你介意详细解释一下“附加到进程”的内容吗?是在IDE或命令行中进行的。 - Corey

2
为了在Linux上调试Web Start应用程序,请按照上述描述创建一个带有javaws调用的shell脚本~/bin/javaws-debug.sh,并处于调试模式:

~/bin/javaws-debug.sh:

#!/bin/sh
export JAVAWS_TRACE_NATIVE=1
export JAVAWS_VM_ARGS="-Xdebug -Xnoagent -Djava.compiler=NONE 
  -Xrunjdwp:transport=dt_socket,address=8989,server=y,suspend=n"
javaws "$@"

然后,在您的浏览器中选择该脚本作为调用jnlp文件的应用程序。

例如,在Firefox中,转到编辑→首选项→应用程序,内容类型:Java Web Start,并在操作中选择“使用其他”,并从“选择辅助应用程序”对话框中选择脚本。在Chrome中,您需要更改Linux系统设置。在KDE中,转到系统设置→文件关联,已知类型:application:x-java-jnlp-file,添加一个新应用程序,并从“选择应用程序以获取application/x-java-jnlp-file”对话框中选择~/bin/javaws-debug.sh。
一旦您的浏览器配置完成,Java Web Start应用程序将开始使用您的包装器,这将使调试器可以连接到8989端口。

1
你尝试打印调试日志了吗?这是一个非常有用的东西,无论如何都可以帮助解决问题。
如果你想要真正的调试,请参考这里:如何在WebStart下进行调试?

直接控制JVM运行的所有方面真的很酷...而且你还可以从启动时的初始屏幕上查找WS启动器添加的所有内容... - Sergey Ushakov

1
这是对我来说有效的方法IcedTea-Web
set JAVAWS_TRACE_NATIVE=1
set JAVA_TOOL_OPTIONS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8989,server=y,suspend=y
javaws -Xnofork my_jnlp_file.jnlp

选项-Xnofork是必需的,否则设置不会应用于应用程序的分叉JVM。

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