如何在运行时调试一个jar包?

54

我现在遇到了一个比较奇怪的问题(从java新手的角度来看):

  1. 使用Eclipse编写了一个“Java程序”(包含一些类的.java文件),该程序主要是批量读取文本*.csv文件,对其内容进行“评估”,并将结果写入*_out.csv文本文件。为了定位输入文件,它使用了一个“文件选择器”(从这里获得示例:http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html

  2. 我已经调试过所有的代码,并且使用调试器,它工作正常

  3. 我运行了代码(主类,按顺序调用所有其他类),在Eclipse中工作正常但是出了Eclipse后就不行了

  4. 我导出了所有项目内容到一个“可运行的jar”文件中。

请注意,文件选择器除外,这基本上是一个批处理程序,只能读写:几乎没有用户界面。在Eclipse中,我使用类似于“if(debug) System.out.print("something to print");”这样的语句显示了一些内部结果,在调试时设置“debug”为TRUE,而在生产环境中设置为FALSE。

以上全部都可以工作!

现在,启动可运行的jar文件(在Win/XP上双击jar文件),我可以看到文件选择器,我可以使用它,但是,在选择了输入文件之后... 就没有更多的反应了:(由于没有用户界面)我不知道文件是否已读取,我也看不到任何生成的输出文件,并且我甚至没有“控制台”来列出任何中间调试消息,以查看jar是否在工作,即使我重新导出并将调试变量设置为TRUE。

有没有一种方法可以像VB的MsgBox或其他工具一样“运行时调试”正在运行的jar?我可以“启用”或查看某个“日志文件”吗?(显然,由于我的jar未编写结果文件,我只能尝试编写*.log文件)

我还要说的是,我在我的机器上除了Eclipse之外,不能安装其他开发工具、实用程序和其他有用的东西。


看一下Lo4j,如果需要一个类似MsgBox的消息框,可以使用JOptionPane。你的程序在Eclipse之外无法正确运行的原因可能是你没有权限(管理员?)读/写这个特定位置,或者你的输出在不同的文件夹中。 - HectorLector
应该使用Log4j,而不是Lo4j。https://logging.apache.org/log4j/2.0/ - JESii
4个回答

125

http://www.eclipsezone.com/eclipse/forums/t53459.html

基本上要用以下命令来运行:

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044

应用程序在启动时会等待您从其他来源连接。

因此,CLI命令将是:

java -jar yourJarFileName.jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044

10
人们是否意识到这条评论有多宝贵? - George
59
对于像我这样的初学者,可以执行java -jar <jarName.jar> -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044命令。然后在Eclipse调试配置中创建一个远程Java应用程序配置,该配置使用1044作为端口号。 - trailblazer
1
我在启动jar的命令中添加了这个,但我仍然无法连接到jdb以调试JVM。当我在jdb -attach 8787(我的端口)后输入时,它会显示“连接被拒绝”。我使用专用用户启动了应用程序,并使用了该命令(他对应用程序拥有完全权限)。有任何想法吗? - Alex
7
请看我的答案,它使用了另一种(更现代的?)命令选项(还请注意命令选项的顺序,先是-agentlib:...,然后是-jar ...,这可能很重要)。链接在这里:https://dev59.com/d2Ij5IYBdhLWcg3w04Xd#38357751。 - Abdull
8
如@Abdull所述,对我来说顺序很重要,因此命令应按以下方式输入:java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044 -jar <jarName.jar> - Bruno Calça
显示剩余3条评论

71

在启动java命令时,您可以使用特殊选项激活JVM的调试能力:

java -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y -jar path/to/some/war/or/jar.jar

在命令行中启动jar.jar将会:

  • 当前JVM实例作为服务器(server=y)监听8000端口(address=8000)
  • stdout输出Listening for transport dt_socket at address: 8000
  • 然后暂停应用程序(suspend=y)直到调试器连接。在这种情况下,调试器扮演客户端的角色。

选择调试器的常见选项包括:

  • Eclipse调试器:在 Run -> Debug Configurations... 下选择 Remote Java Application,点击 New launch configuration 按钮。提供此调试配置的任意 NameConnection Type: Standard (Socket Attach),并使用 Connection Properties 中的条目 Host: localhostPort: 8000。点击 Apply 更改并点击 Debug。当Eclipse调试器成功连接到JVM时,jar.jar 应该开始执行。
  • jdb 命令行工具:使用 jdb -connect com.sun.jdi.SocketAttach:port=8000 启动它。

1
仅为JDK 1.4x添加的是-Xdebug -Xrunjdwp:transport = dt_socket,server = y,suspend = n,address = 1044,而对于JDK 1.3或更早版本,则为:-Xnoagent -Djava.compiler = NONE -Xdebug -Xrunjdwp:transport = dt_socket,server = y,suspend = n,address = 1044。 - cabaji99
我认为这应该被选为正确答案,因为解释非常精确地针对了标题 - “如何调试jar文件”。另一个正确答案肯定会解决问题,但是那个解释与标题主题不同,因此当前标记的正确答案可能无法帮助来到本线程寻找可执行jar文件调试解决方案的人们。 - Maulik Kayastha

17
即使它是可运行的jar文件,您仍然可以从控制台运行它--打开终端窗口,导航到包含该jar文件的目录,并输入“java -jar yourJar.jar”。它将在该终端窗口中运行,并且sysout和syserr输出将出现在其中,包括未捕获异常的堆栈跟踪。编译时请确保您的调试设置为true。祝您好运。
刚想到另一件事-如果您使用的是Win7,通常会出现用户应用程序向特定目录写入文件时的权限问题。确保您要写入输出文件的目录是您具有权限的目录之一。
在将来的项目中,如果足够大,您可以使用标准日志记录工具来进行“调试”输出;然后将其重定向到文件而不是依赖于控制台将更容易。但对于像这样的较小作业,这应该是可以的。

1
非常感谢rcook,您的解决方案完全解决了我的问题:我没有想到当直接调用JVM时,它会将stdout和stderr“导出”到控制台(事实上问题不在于没有本地控制台)。 该程序依赖于一对文本文件(配置和其他),应该是“外部”的:当在Eclipse中时,文件可用于文件系统,但在JAR中时则不可用。 现在,我将文本文件从JAR中复制出来,程序立即工作了。:-) @RamonBoza:我在我的计算机上几乎没有权限,在网络计算机上也没有权限。 :-/ - eewing
只是提供信息:不需要写入的文件可以放在jar包中,然后作为“资源”访问--查找有关Class.getResource()和相关方法的教程。很高兴这有所帮助。 - arcy
如果你正在使用Windows 10并启用了Windows Defender的控制文件夹访问功能,那么它会导致相同的问题。只需为你的应用程序提供访问权限即可大有裨益。 - maazakn

3
使用 IntelliJ IDEA,您可以创建一个Jar应用程序运行配置,选择JAR、源代码、要使用的JRE以及启动调试。这里是相关文档。

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