如何在运行我的代码时调试JVM中发生的Segfaults?

时间:2011-08-30 22:40:15

标签: java segmentation-fault

我的Java应用程序已经开始定期崩溃,包括SIGSEGV和堆栈数据转储以及文本文件中的大量信息。

我在gdb中调试了C程序,并且已经从IDE调试了Java代码。我不确定如何在正在运行的Java程序中处理类似C的崩溃。

我假设我不是在看这里的JVM错误。其他Java程序运行得很好,Sun的JVM可能比我的代码更稳定。但是,我不知道我怎么能用Java代码导致段错误。肯定有足够的可用内存,当我上次检查分析器时,堆使用率约为50%,偶尔会出现80%左右的峰值。我可以调查任何启动参数吗?在接近像这样的bug时,什么是好的清单?

虽然我不能够可靠地重现这个事件,但它似乎也不是完全随机发生的,所以测试并非完全不可能。

ETA:一些血腥的细节

(我正在寻找一种通用的方法,因为实际的问题可能非常具体。但是,我已经收集了一些信息,这可能有一些价值。)

前一段时间,我在升级CI服务器后遇到了类似的问题(有关详细信息,请参阅here),但该修复程序(设置-XX:MaxPermSize)此时无效。

进一步的调查显示,在崩溃日志文件中,标记为“当前线程”的线程从来都不是我的,但是任何一个称为“VMThread”或称为“GCTaskThread”的线程 - 如果是后者,则另外标记注释“(退出)”,如果是前者,则GCTaskThread不在列表中。这让我想到问题可能是在GC操作结束时。

5 个答案:

答案 0 :(得分:22)

  

我假设我不是在看这里的JVM错误。其他Java程序   运行得很好,Sun的JVM可能比我的更稳定   代码。

我认为你不应该做出这样的假设。不使用JNI,您应该无法编写导致SIGSEGV的Java代码(尽管我们知道它发生了)。我的观点是,当它发生时,它要么是JVM中的一个错误(不是闻所未闻),要么是某些JNI代码中的错误。如果你自己的代码中没有任何JNI,那并不意味着你没有使用某个库,所以请寻找它。当我之前看到这种问题时,它出现在图像处理库中。如果罪魁祸首不在您自己的JNI代码中,您可能无法“修复”该错误,但您仍然可以解决它。

首先,您应该在同一平台上获得备用JVM并尝试重现它。您可以尝试one of these alternatives

如果无法重现,可能是JVM错误。从那里,您可以使用您知道的有关如何重现它的任务来强制使用特定的JVM或search the bug database,也可以获得建议的解决方法。 (即使你可以重现它,许多JVM实现只是对Oracle的Hotspot实现的调整,所以它可能仍然是一个JVM错误。)

如果您可以使用备用JVM重现它,则错误可能是您有一些JNI错误。查看您正在使用的库以及它们可能正在进行的本机调用。有时,对于相同的库或替代库,有替代的“纯Java”配置或jar文件几乎完全相同。

祝你好运!

答案 1 :(得分:9)

除非您有本机代码,否则以下内容几乎肯定无用。但是,这里有。

  1. 在java调试器中启动java程序,在可能的sigsegv之前使用断点。
  2. 使用ps命令获取java的处理代码。
  3. gdb / usr / lib / jvm / sun-java6 / bin / java processid
  4. 确保gdb'handr'命令设置为在SIGSEGV上停止
  5. 从断点继续java调试器。
  6. 等待爆炸。
  7. 使用gdb进行调查
  8. 如果您真的设法让JVM在没有自己的本机代码的情况下使用sigsegv,那么您很可能不会对下一步会看到什么有任何意义,并且您可以做的最好就是推送测试用例在错误报告上。

答案 2 :(得分:2)

我在http://www.oracle.com/technetwork/java/javase/crashes-137240.html找到了一份好的名单。当我在GC期间遇到崩溃时,我会尝试在垃圾收集器之间切换。

我尝试在串行和并行GC之间切换(后者是64位Linux服务器上的默认值),这只会相应地更改错误消息。

在分析器中进行全新分析后,将最大堆大小从16G减少到10G(这使我的堆使用率在8G时变平)确实导致“虚拟内存”占用空间明显减少(16G而不是60),但是我甚至不知道这意味着什么,互联网说,这没关系。

目前,JVM正在客户端模式下运行(使用-client启动选项,从而覆盖默认值-server)。到目前为止,没有崩溃,但性能影响似乎相当大。

答案 3 :(得分:0)

如果你有一个核心文件,你可以尝试在其上运行jstack,这会给你一些更易于理解的东西 - 请参阅http://download.oracle.com/javase/6/docs/technotes/tools/share/jstack.html,尽管如果它是gc线程中的一个错误,它可能没有那么有用。

答案 4 :(得分:0)

尝试检查c程序carh是否导致java崩溃。使用valgrind知道无效并且还交叉检查堆栈大小。