翻译于《Troubleshooting Guide for JavaSE6 with HotSpotVM》
1. 生成位置
-XX:ErrorFile=/fullpath/file,file里可以包含%p表示进程id。如果没声明,默认的名字是hs_err_pid.log,保存在进程的工作目录。如果因为权限和空间等问题不能存在工作目录,会保存在系统的临时目录
2. 包含信息
导致fatal error的操作异常或signal
版本和配置信息
导致fatal error的线程和堆栈
正在执行的线程及其状态
堆的summary
加载的native library
命令行参数
环境变量
操作系统和CPU细节
3. Header
SIGSEGV (0xb) at pc=0x417789d7, pid=21139, tid=1024
| | | | +--- thread id
| | | +------------- process id
| | +--------------------------- program counter
| | (instruction pointer)
| +--------------------------------------- signal number
+---------------------------------------------- signal name
还有可能是internal error等
“EXCEPTION_STACK_OVERFLOW”意味着这是个栈溢出的错误。
“EXCEPTION_ACCESS_VIOLATION ”意味着Java应用Crash的时候,正在运行JVM自己的代码,而不是外部的Java代码或其他类库代码。
导致error的frame
# Problematic frame:
# C [libNativeSEGV.so+0x9d7]
Frame Type Description
C Native C frame
j Interpreted Java frame
V VM frame
v VM generated stub frame
J Other frame types, including compiled Java frame
4. 线程信息
Current thread (0x0805ac88): JavaThread "main " [_thread_in_native, id=21139]
| | | | +-- ID
| | | +------------- state
| | +-------------------------- name
| +------------------------------------ type
+-------------------------------------------------- pointer
线程类型可能有:
JavaThread
VMThread
CompilerThread
GCTaskThread
WatcherThread
ConcurrentMarkSweepThread
线程状态
Thread State Description
_thread_uninitialized Thread is not created. This occurs only in the case of memorycorruption.
_thread_new Thread has been created but it has not yet started.
_thread_in_native Thread is running native code. The error is probably a bug in nativecode.
_thread_in_vm Thread is running VM code.
_thread_in_Java Thread is running either interpreted or compiled Java code.
_thread_blocked Thread is blocked.
siginfo:
在Solaris OS和Linux signal number ( si_signo ) 和 signal code (si_code)用于标示错误信息:
siginfo:si_signo=11, si_errno=0, si_code=1, si_addr=0x00004321
寄存器信息
机器指令
线程堆栈
可能有native和java两种
两个例子:
内存回收引起的Crash内存回收引起的Crash有以下的特点:在日志文件头一般有“ EXCEPTION_ACCESS _VIOLATION”和“# Problematic frame: # V [jvm.dll+....”的信息
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [jvm.dll+0x15e87e]
VM_Operation (0x063efbac): full generation collection, mode: safepoint, requested by thread 0x040f83f8
可以看到JVM正在做 “full generation collection”。另外还有可能看到,其他的回收行为:
generation collection for allocation
full generation collection
parallel gc failed allocation
parallel gc failed permanent allocation
parallel gc system gc
栈溢出引起的Crash
Java代码引起的栈溢出,通常不会引起JVM的Crash,而是抛出一个Java异常:java.lang.StackOverflowError。
但是在Java虚拟机中,Java的代码和本地C或C++代码公用相同的Stack。这样,在执行本地代码所造成的栈溢出,
就有可能引起JVM的Crash了。
栈溢出引起的Crash会在日志的文件头中看到“EXCEPTION_STACK_OVERFLOW”字样。另外,在当前线程的Stack
信息中也能发现一些信息。例如下面的例子:
-----------------------------------------------------------------------------------
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x10001011, pid=296, tid=2940
#
# Java VM: Java HotSpot(TM) Client VM (1.6-internal mixed mode, sharing)
# Problematic frame:
#
C [App.dll+0x1011]
#
--------------- T H R E A D ---------------
Current thread (0x000367c0): JavaThread "main" [_thread_in_native, id=2940]
:
Stack: [0x00040000,0x00080000), sp=0x00041000, free space=4k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [App.dll+0x1011]
C [App.dll+0x1020]
C [App.dll+0x1020]
:
C [App.dll+0x1020]
C [App.dll+0x1020]
...<more frames>...
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j Test.foo()V+0
j Test.main([Ljava/lang/String;)V+0
v ~StubRoutines::call_stub
--------------------------------------------------------------------------------
在上面的信息中,可以发现这是个栈溢出的错误。并且当前栈剩余的空间已经很小了(free space =4k)。
因此建议将JVM的Stack的尺寸调大,主要设计两个参数:“-Xss” 和“-XX:StackShadowPages=n”。
但是,将栈的尺寸调大,也意味着在有限的内存资源中,能打开的最大线程数会减少。
5. 进程信息:线程列表和内存使用情况
VMState:虚拟机状态
General VM State Description
not at a safepoint Normal execution.
at safepoint All threads are blocked in the VM waiting for a special VM operation tocomplete.
synchronizing A special VM operation is required and the VM is waiting for all threads in the VM to block.
堆信息:
虚拟机参数和环境变量
6. 系统信息
操作系统、cpu、内存配置
比较牛逼的错误定位:
1. 查看hs_err_pidXXXX.log中的ESP,EBP等信息,以及Top of Stack的信息确定调用堆栈,找到入口地址
2. 查看hs_err_pidXXXX.log中的dll加载信息,确定dll的加载地址,使用入口地址-加载地址可得到函数的偏移
3. 使用objdump或者反汇编工具,用dll的基址+偏移定位dll中的代码,基本上就可以找到出现问题的位置。