【发布时间】:2009-09-28 09:06:28
【问题描述】:
我正在开发 Java 产品。客户声称应用程序在任意时间后崩溃。因为这是一次崩溃,我们在日志中找不到任何信息。
是否有任何工具、方法可以找出此类问题的原因?
我们可以在代码方面做些什么来获取有关此类程序崩溃的更多信息吗?
我们可以为 JVM 启用“调试”模式吗?如果是这样,我在哪里可以找到 JVM 日志文件/故障转储?
任何已知的程序来处理此类问题?
如果您遇到此问题,您的故障排除程序是什么?
【问题讨论】:
我正在开发 Java 产品。客户声称应用程序在任意时间后崩溃。因为这是一次崩溃,我们在日志中找不到任何信息。
是否有任何工具、方法可以找出此类问题的原因?
我们可以在代码方面做些什么来获取有关此类程序崩溃的更多信息吗?
我们可以为 JVM 启用“调试”模式吗?如果是这样,我在哪里可以找到 JVM 日志文件/故障转储?
任何已知的程序来处理此类问题?
如果您遇到此问题,您的故障排除程序是什么?
【问题讨论】:
我很难相信 JVM 崩溃时没有输出。首先仔细检查你的运行脚本,看看你是否只是忽略了输出。如果JVM由于未处理的异常而结束,我相信它会将异常输出到stdout。如果它严重崩溃(堆损坏等),它将向标准错误输出一些东西。您的应用程序内日志记录很有用,但您也应该记录进入 stdout 和 stderr 的任何输出(您没有定义您的应用程序运行的平台,但这基本上适用于所有平台)。
除此之外,您还可以传递大量非标准选项来定义错误文件的位置等,请参阅Java HotSpot VM Options。
【讨论】:
我会将您的应用程序日志调整为详细级别或调整 JVM,如前所述,但如果您想要更多选项,您可以尝试 JVisualVM 来观察一些奇怪的东西(内存/线程/gc/jmx 操作),最后机会,我会搜索 hs_err_pid*.log 文件。 这些文件包含有关 JVM 在硬崩溃时的状态信息(内存违规等)。 这里有一个例子:
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d741e3a, pid=1572, tid=1364
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_11-b03 mixed mode)
# Problematic frame:
# V [jvm.dll+0x1e3a]
#
--------------- T H R E A D ---------------
Current thread (0x00a85c78): VMThread [id=1364]
siginfo: ExceptionCode=0xc0000005, reading address 0x00000054
Registers:
EAX=0x00000050, EBX=0x00990000, ECX=0x0847b9f8, EDX=0x00000050
ESP=0x0ab0f660, EBP=0x0ab0f684, ESI=0x0847b9f8, EDI=0x0847b9f8
EIP=0x6d741e3a, EFLAGS=0x00010216
【讨论】:
崩溃后,您没有崩溃期间的日志,但您仍然拥有实际崩溃之前的所有日志。如果您的日志足够详细,那应该会为您提供大量信息。
在 java 中,您将两个阶段结合起来:
debug级别的单个类的日志一样具体,而其余的仅在error级别),以获得良好的性能和日志可接受大小的文件。利用日志记录的力量,你应该能够一点一点地缩小你的注意力。请注意,如果您的应用程序的日志太少,您应该尽快开始添加更多日志(当然是在适当的日志级别)。示例流程:
error 级别,看看你会得到什么warning 级别,看看你会得到什么info级别的一个包,看看你得到什么debug 一个班级的等级,看看你得到了什么【讨论】:
如果此问题仅发生在该客户端,请询问他们是否在多台计算机上运行该应用程序。如果是,问题是否发生在所有人身上?
如果问题只出现在一台机器上,我怀疑硬件有问题,很可能是 RAM。这可以使用memtest 之类的工具进行诊断。
我个人只亲眼目睹了两次 JVM 反复崩溃的实例。在这两种情况下,问题都是 RAM 有问题。
【讨论】:
一些有助于诊断内存问题的选项:
如果虚拟机因内存耗尽而退出,JVM 选项-XX:+HeapDumpOnOutOfMemoryError 将创建堆转储。您可以使用 eclipseMAT 之类的工具分析转储以确定问题的原因。
此外,-verbose:gc 将提供详细的垃圾收集统计信息,添加 -Xloggc:<file> 会将其重定向到文件。
【讨论】:
如果您使用的是 JNI(或任何使用 JNI 的库),则很容易使 JVM 崩溃,以至于它根本不会留下任何痕迹。据我所知,调试此类问题的唯一方法是使用调试器单步调试本机内容。
【讨论】:
除了所有其他建议之外,请检查您的代码库中是否有对 System.exit() 的调用。
【讨论】: