我在调试会话中遇到了问题。 我的程序在调试会话中执行得非常好,但如果我开始正常运行,它的行为就完全不同。
问题是我不能确定为什么会有差异。
可能的原因之一是执行时间较慢,因为您总是需要按F6或类似键。
我尝试插入 Thread.sleep(1000);
,但我不知道引起不同行为的指令。
那么:有哪些提示和最佳实践可以了解为什么在调试会话中表现如此不同?
我在调试会话中遇到了问题。 我的程序在调试会话中执行得非常好,但如果我开始正常运行,它的行为就完全不同。
问题是我不能确定为什么会有差异。
可能的原因之一是执行时间较慢,因为您总是需要按F6或类似键。
我尝试插入 Thread.sleep(1000);
,但我不知道引起不同行为的指令。
那么:有哪些提示和最佳实践可以了解为什么在调试会话中表现如此不同?
两种解决方案:
a) 使用简易的调试工具(打印到控制台)或使用日志框架,当出现错误时,分析输出信息。
b) 编写测试用例以尝试重现问题。即使您无法通过此方法找到问题,这也可以清理代码并有时解决问题。
java.io.PrintStream.println(String)
调用同步,这会导致延迟等问题(例如,在你调试的资源上竞争?)。因此,即使是简单的调试器也可能会产生意想不到的副作用。请参见:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/io/PrintStream.java#PrintStream.println%28java.lang.String%29 - Dan Barowy如果没有减缓执行速度的调试语句,您可能会观察到仅在这种情况下发生的竞争条件。从审查线程模型开始,并注意任何可能的锁定可能会有所帮助。
我试图检查我的假设并再次检查它们。
过度记录在某些情况下可能有所帮助,但并非总是如此。在我的情况下,并没有帮助太多。
使用记录,您可以看到您的假设正确的地方和哪些失败了。
我的个人解决方案是针对Java的特定情况。自JDK 1.5以来,Java ClassLoader不会完全加载类。在调试会话中,必须完全加载。因此,某些变量未初始化良好,输出与正常运行不同。
这个原因很难找到。
调试多线程应用程序确实很困难。
你可以尝试使用旧的System.out.println技术进行调试,而不是使用调试器...也许这样可以在具有你提到的不同行为时进行调试。
Manu
注意:不一定与多线程相关。
有时候,为我解决问题的方法是设置不同的断点。
有时候,评估值会改变它们的值(例如读取迭代器的值)。
其次,您的“错误”断点可能会阻碍并行性和竞争条件。
首先检查一些简单的东西。崩溃版本是否获得相同的命令行参数?或特殊环境变量?或用户ID?或其他你知道很重要的因素。换句话说,你是否真的使用相同的输入运行它。
它是否总是崩溃?它是否在同一个地方崩溃?如果你可以在崩溃后连接调试器,那么它停止工作的地方可能会提供一些线索。最近的某些更改是否可能是罪魁祸首?如果是这样,请尝试删除它并观察发生了什么。
不要过于纠结于这些尝试。它们只是猜测,如果能够快速解决问题就很好,但最终是无效的,因为“在调试状态下运行”和“自由运行”之间有数百万种可能的差异。
否则,切断差分分析并解决问题。也就是说,直接查看崩溃时出现的问题,而不是迭代可能的原因。
以下是一些书籍摘录,可能会帮助您“在没有调试器的情况下进行调试”。
祝你好运!
我遇到了类似的问题。
我的问题是:Set.iterator
在 debug
和 run
中产生了不同的结果。
当然,我的代码存在一个错误,间接地依赖于集合元素的顺序。