如何在运行时调试 jar?

Posted

技术标签:

【中文标题】如何在运行时调试 jar?【英文标题】:how can I debug a jar at runtime? 【发布时间】:2013-11-19 11:24:10 【问题描述】:

我处于一个非常奇怪的位置(从我的 java 新手的角度来看):

    使用 Eclipse 我编写了一个“java 程序”(一些带有类的 .java 文件),它基本上(批量)读取文本 *.csv 文件,“评估”其内容,并将结果写入 * _out.csv 文本文件。要找到输入文件,它使用“文件选择器”(从此处获取示例:http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html

    我调试了所有代码,并且使用调试器可以正常工作

    我运行了代码(主类,它依次调用所有其他类)并且它可以工作在 Eclipse 中

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

请注意,除了文件选择器,这主要是一个读写的“批处理”:几乎没有用户界面。在进入 Eclipse 时,我使用类似“if(debug) System.out.print("something to print");” 提供设置“debug”之类的东西显示了一些内部结果调试时为 TRUE,生产环境中为 FALSE。

以上所有工作!

现在,启动可运行的 jar(在 Win/XP 中双击 jar 文件),我可以看到文件选择器,我可以使用它,但是,在选择输入文件之后。 .. 仅此而已:(没有用户界面)我不知道文件是否被读取,我没有看到任何生成的输出文件,我什至没有“控制台”可以列出任何中间调试消息,以查看 jar 是否正常工作,即使我在调试变量设置为 TRUE 的情况下重新导出它。

有没有办法“运行时调试”正在运行的 jar(如 VB 的 MsgBox 或其他)?我可以“启用”或查看某种“日志文件”? (显然,由于我的 jar 没有写入结果文件,我也无法尝试写入 *.log) 我还必须说,我只是无法在我的机器上安装除 Eclipse 之外的其他东西(幸运的是它运行了),所以没有通常的开发人员工具、实用程序和其他有用的东西。

【问题讨论】:

看看 Lo4j,对于 MsgBox 样式的消息,请使用 JOptionPane。您的程序在 Eclipse 之外无法正常运行的原因可能是您无权(管理员?)在此特定位置读/写,或者您的输出位于不同的文件夹中? 应该是 Log4j,而不是 Lo4j。 logging.apache.org/log4j/2.0 【参考方案1】:

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

基本上运行它:

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

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

【讨论】:

大家知道这条评论的价值吗? 对于像我这样的愚蠢的人,做一个java -jar <jarName.jar> -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044。然后去eclipse调试配置,创建一个使用1044作为端口的远程java应用配置。 我在命令中添加了这个来启动 jar,但我仍然无法将 jdb 连接到调试 JVM。当我在 jdb -attach 8787 (我使用的端口)之后键入时,它失败并显示“连接被拒绝”。我使用专用用户和此命令启动了应用程序(他拥有应用程序的全部权限)。有什么想法吗? @Alex 请参阅my answer,它使用另一个(更现代的?)命令选项(还请注意命令选项的顺序 [首先是 -agentlib:...,然后是 -jar ... 可能很重要)。跨度> 正如@Abdull 所说,订单对我很重要,所以java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=1044 -jar <jarName.jar>【参考方案2】:

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

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

像这样在命令行启动jar.jar会:

this JVM 实例置于监听 8000 端口 (address=8000) 的服务器 (server=y) 角色 将Listening for transport dt_socket at address: 8000 写入stdout 和 然后暂停应用程序 (suspend=y) 直到某个调试器连接。在这种情况下,调试器充当客户端

选择调试器的常用选项有:

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

【讨论】:

只为 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 我认为这应该被选为正确答案,因为解释是准确的标题 - “我如何调试 jar 文件”。另一个正确答案肯定会解决问题,但该解释与标题主题行不同,因此当前标记的正确答案可能无助于进入该线程的人寻找调试可执行 jar 文件的解决方案。跨度> 【参考方案3】:

即使它是一个可运行的 jar,您仍然可以从控制台运行它——打开一个终端窗口,导航到包含该 jar 的目录,然后输入“java -jar yourJar.jar”。它将在该终端窗口中运行,并且 sysout 和 syserr 输出将出现在那里,包括来自未捕获异常的堆栈跟踪。确保在编译时将调试设置为 true。祝你好运。


只是想到了一些别的东西——如果你在 Win7 上,它通常会在用户应用程序将文件写入特定目录时遇到权限问题。确保您写入输出文件的目录是您有权访问的目录。

在未来的项目中,如果它足够大,您可以使用标准日志工具之一进行“调试”输出;那么将它重定向到文件而不是依赖于控制台将很容易(ier)。但是对于这样一个较小的工作,这应该没问题。

【讨论】:

非常感谢 rcook,您的解决方案完全解决了我的问题:我没有想到,当直接调用 JVM 时,它会将 stdout 和 stderr “导出”到控制台(作为事实上问题是没有本地控制台)。该程序依赖于几个应该是“外部”的文本文件(配置和其他):在 Eclipse 中,文件对文件系统可用,但在 JAR 中则不可用。现在我从 JAR 中复制了文本文件,程序立即运行。 :-) @RamonBoza:我对我的机器几乎没有权利,对联网机器也没有权利。 :-/ 仅供参考:您不需要写入的文件可以放在 jar 中,然后作为“资源”访问——查看 Class.getResource() 和相关方法的教程.很高兴这有帮助。 它很有帮助,如果您在 Windows 10 上并且从 Windows Defender 启用了控制文件夹访问,那么它会导致同样的问题。刚刚授予对您应用程序的访问权限。【参考方案4】:

使用IntelliJ IDEA,您可以创建Jar Application 运行时配置,选择JAR、源、JRE 以运行Jar 并开始调试。 Here 是文档。

【讨论】:

以上是关于如何在运行时调试 jar?的主要内容,如果未能解决你的问题,请参考以下文章

如何在应用程序未运行并点击推送通知时调试远程推送通知?

如何在旧版本仍在运行时调试 Discord 机器人?

如何在Golang中运行exec.Command时调试“exit status 1”错误

如何在保存时调试 CoreData 崩溃?

如何在开发时调试 nopCommerce 插件?

如何在展开可选值时调试“nil 的致命错误”?