Java中Heisenbugs的可能和不太可能的原因?

时间:2016-01-08 14:51:09

标签: java heisenbug jpda

我有一个经典的Heisenbug例子是由我以前从未见过的情况引发的。我的遗留应用程序(大约100K旧代码)无法在特定实例中正常工作,仅仅启用JPDA进行远程调试就足以改变行为,导致应用程序正常工作:除了添加“-Xdebug -Xnoagent -Xrunjdwp之外什么都不做: transport = dt_socket,server = y,suspend = n,address = 6666“到vm的命令行隐藏了bug(有或没有实际连接)。鉴于我有一个完全可重复的测试用例,我讨厌在代码更改的情况下对其进行干扰,以防它重新隐藏。当然,这只是在生产中发生的。

通常,我会立即假设一个线程问题,但是a)行为是100%失败而100%工作,b)在相关代码路径中没有明确使用线程。然后我们的团队试图找出这种行为的其他原因列表,所以我想也许Stack Overflow的团队思想可能会增加更多。

Java中的Heisenbugs:

  • 线程:错误的同步,竞争条件,隐式排序假设。
  • 显式调试/记录代码:代码路径中的更改会导致/防止出现问题。不太经常,日志级别的更改可能导致时序更改(再次线程化)和I / O资源使用的差异。
  • 本机代码库可以拖入非Java Heisenbug问题。
  • 期待终结者可以预测地运行。
  • 关于弱引用的错误假设。
  • 假设固定大小的缓存永远不会填满。
  • 期待哈希码的唯一性。
  • 假设==适用于字符串(或者不适用于可能在某些情况下被实习的字符串)。
  • VM bug(不,从不发生;)。
  • 测试方法错误。特别是当存在依赖于测试成功的隐藏变量时。 (这看起来是我们的实际问题。一次测试的成功导致客户运行下一次测试,由于策略问题而失败。失败导致根据策略在调试模式下运行,这导致成功。叹气)

还有其他值得探索的案例吗?

编辑

  • 是的,JPDA启用代码使用旧语法。我没有测试过使用现代语法是否也会改变行为。
  • 此特定计算机使用1.8.0_45-b14作为JRE,而HotSpot 64位服务器VM(版本25.45-b02)
  • 虽然问题是一般的,但鼓动的​​问题是真实的和最新的。由于这个问题在已部署的系统中出现,我想要让它与-Xdebug一起运行作为一种解决方法,以便它保持运行并想要追踪底层错误并将其杀死。
  • 有问题的程序是多步骤数据处理管道的一部分 - 细节无关紧要,但可以最好地理解为从数据库获取一些信息然后用它来修改某些文件的独立应用程序。系统中破坏的部分似乎是来自数据库的信息没有被正确解释 - 来自破坏的对象ORM或缓存的任何东西。当它“被破坏”时,确定它是否有工作要做的应用程序逻辑(基于db的内容)对所有迭代(数千次迭代,包括程序的多次调用)做出错误的选择。当它“工作”时(唯一的区别是vm与-Xdebug一起运行),应用程序为所有迭代做出正确的选择。它在此配置中完全一致。针对不同数据库运行的相同代码不会失败。有一些证据(在我参与此代码之前),过去看到的类似行为在看似微不足道的代码变化之后神秘地开始工作......参见“Heisenbug”

2 个答案:

答案 0 :(得分:4)

-Xdebug似乎是一个行为改变开关。 What are Java command line options to set to allow JVM to be remotely debugged?声称添加它会使您从JIT变为所有解释。其他oracle java docs(for jrocket admittedly)似乎表明它由于某些未指明的原因而变慢,并且它不适合已部署的系统。

我可以想象不同的GC方案可能会进行更改。

答案 1 :(得分:3)

我遇到了一个案例,其中故障是由硬件上的节能功能引起的,当该bug正在研究中时,该功能从未被激活。