原文地址: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/crashes001.html
这几天公司其他组遇到了一个segmentation fault的问题,找到了这个官方文档,基于Java8,感觉不错就翻译了下.
一些地方翻译比较生硬,如有问题请麻烦指正~^_^ by fairjm
5.1 确定崩溃何地发生
这一节提供了一些例子来演示如何使用错误日志来找到崩溃的原因,并且给出一些排查这些问题的建议.
错误日志的头指出了错误的类型和有问题的帧(frame),thread stack指出了当前的线程和堆栈轨迹.查看Header Format
Crash in Native Code
Crash in Compiled Code
Crash in HotSpot Compiler Thread
Crash in VM Thread
Crash Due to Stack Overflow
5.1.1 本地代码崩溃
如果致命错误日志(fatal error log)指出的问题帧来自于本地库,那么可能是本地库或者JNI库代码存在bug.这种崩溃当然也有可能是其他原因造成的,但是分析这个库和其他的core file或者crash dump是一个很好的开始.
以下是一个致命错误日志的头:
# An unexpected error has been detected by HotSpot Virtual Machine: # # SIGSEGV (0xb) at pc=0x417789d7, pid=21139, tid=1024 # # Java VM: Java HotSpot(TM) Server VM (6-beta2-b63 mixed mode) # Problematic frame: # C [libApplication.so+0x9d7]在这个例子中,SIGSEGV发生在线程执行libApplication.so中的代码.
一些其他例子是Java VM的本地库导致的.在下面的例子中,JavaThread在_thread_in_vm状态中失败了(表明它正在执行Java VM代码)
# An unexpected error has been detected by HotSpot Virtual Machine: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x08083d77, pid=3700, tid=2896 # # Java VM: Java HotSpot(TM) Client VM (1.5-internal mixed mode) # Problematic frame: # V [jvm.dll+0x83d77] --------------- T H R E A D --------------- Current thread (0x00036960): JavaThread "main" [_thread_in_vm, id=2896] : Stack: [0x00040000,0x00080000), sp=0x0007f9f8, free space=254k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) V [jvm.dll+0x83d77] C [App.dll+0x1047] <========= C/native frame j Test.foo()V+0 j Test.main([Ljava/lang/String;)V+0 v ~StubRoutines::call_stub V [jvm.dll+0x80f13] V [jvm.dll+0xd3842] V [jvm.dll+0x80de4] V [jvm.dll+0x87cd2] C [java.exe+0x14c0] C [java.exe+0x64cd] C [kernel32.dll+0x214c7] :在这个例子中,虽然出问题的帧是VM的,线程栈显示一个本地例子(native routine)App.dll已经被VM调用(可能是通过JNI).
解决这个本地库崩溃的第一步是调查本地库发生崩溃的那段源代码.
- 如果本地库是由你的应用程序提供,那么调查本地库的源代码.大量的问题可以通过在运行应用程序时使用
-Xcheck:jni参数被识别.查看The -Xcheck:jni Option. - 如果这个本地库是由其他供应商提供,被你的程序所使用,那么就向他们提供bug报告和致命错误日志信息.
- 如果本地库是来自于JRE的(比如awt.dll,net.dll或其他的),那有可能你遇到了一个库或者API的bug.那么就尽可能获取足够的信息提交一个bug并指名库名称.你可以在JRE的发行版中的 jre/lib 或 jre/bin目录中找到JRE的库.
