一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - jvm crash的崩潰日志詳細分析及注意點

jvm crash的崩潰日志詳細分析及注意點

2020-09-05 12:06raintungli Java教程

本篇文章主要介紹了jvm crash的崩潰日志詳細分析及注意點。具有很好的參考價值,下面跟著小編一起來看下吧

生成

1. 生成error 文件的路徑:你可以通過參數設置-XX:ErrorFile=/path/hs_error%p.log, 默認是在Java運行的當前目錄 [default: ./hs_err_pid%p.log]

2. 參數-XX:OnError  可以在crash退出的時候執行命令,格式是-XX:OnError=“string”,  <string> 可以是命令的集合,用分號做分隔符, 可以用"%p"來取到當前進程的ID.

例如:

?
1
2
// -XX:OnError="pmap %p"  // show memory map
// -XX:OnError="gcore %p; dbx - %p" // dump core and launch debugger

在Linux中系統會fork出一個子進程去執行shell的命令,因為是用fork可能會內存不夠的情況,注意修改你的 /proc/sys/vm/overcommit_memory 參數,不清楚為什么這里不使用vfork

3. -XX:+ShowMessageBoxOnError 參數,當jvm crash的時候在linux里會啟動gdb 去分析和調式,適合在測試環境中使用。

什么情況下不會生成error文件

linux 內核在發生OOM的時候會強制kill一些進程, 可以在/var/logs/messages中查找

Error crash 文件的幾個重要部分

a.  錯誤信息概要

?
1
2
3
4
5
6
7
8
9
10
11
12
13
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x0000000000043566, pid=32046, tid=1121192256
#
# JRE version: 6.0_17-b04
# Java VM: Java HotSpot(TM) 64-Bit Server VM (14.3-b01 mixed mode linux-amd64 )
# Problematic frame:
# C 0x0000000000043566
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.

SIGSEGV 錯誤的信號類型

pc 就是IP/PC寄存器值也就是執行指令的代碼地址

pid 就是進程id

# Problematic frame:
# V  [libjvm.so+0x593045]

就是導致問題的動態鏈接庫函數的地址

pc 和 +0x593045 指的是同一個地址,只是一個是動態的偏移地址,一個是運行的虛擬地址

b.信號信息

Java中在linux 中注冊的信號處理函數,中間有2個參數info, ucvoid

?
1
2
3
4
5
6
7
8
9
10
static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
 // unmask current signal
 sigset_t newset;
 sigemptyset(&newset);
 sigaddset(&newset, sig);
 sigprocmask(SIG_UNBLOCK, &newset, NULL);
 
 VMError err(NULL, sig, NULL, info, ucVoid);
 err.report_and_die();
}

在crash report中的信號錯誤提示

siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x0000000000043566 

信號的詳細信息和si_addr 出錯誤的內存,都保存在siginfo_t的結構體中,也就是信號注冊函數crash_handler里的參數info,內核會保存導致錯誤的內存地址在用戶空間的信號結構體中siginfo_t,這樣在進程在注冊的信號處理函數中可以取得導致錯誤的地址。

c.寄存器信息

?
1
2
3
4
5
6
7
Registers:
RAX=0x00002aacb5ae5de2, RBX=0x00002aaaaf46aa48, RCX=0x0000000000000219, RDX=0x00002aaaaf46b920
RSP=0x0000000042d3f968, RBP=0x0000000042d3f9c8, RSI=0x0000000042d3f9e8, RDI=0x0000000045aef9b8
R8 =0x0000000000000f80, R9 =0x00002aaab3d30ce8, R10=0x00002aaaab138ea1, R11=0x00002b017ae65110
R12=0x0000000042d3f6f0, R13=0x00002aaaaf46aa48, R14=0x0000000042d3f9e8, R15=0x0000000045aef800
RIP=0x0000000000043566, EFL=0x0000000000010202, CSGSFS=0x0000000000000033, ERR=0x0000000000000014
 TRAPNO=0x000000000000000e

寄存器的信息就保存在b部分的信號處理函數參數 (ucontext_t*)usVoid中

在X86架構下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
void os::print_context(outputStream *st, void *context) {
 if (context == NULL) return;
 
 ucontext_t *uc = (ucontext_t*)context;
 st->print_cr("Registers:");
#ifdef AMD64
 st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
 st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
 st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
 st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
 st->cr();
 st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
 st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
 st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
 st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
 st->cr();
 st->print( "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
 st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
 st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
 st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
 st->cr();
 st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
 st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
 st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
 st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
 st->cr();
 st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
 st->print(", EFL=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
 st->print(", CSGSFS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_CSGSFS]);
 st->print(", ERR=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ERR]);
 st->cr();
 st->print(" TRAPNO=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_TRAPNO]);
#else
 st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EAX]);
 st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBX]);
 st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ECX]);
 st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDX]);
 st->cr();
 st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_UESP]);
 st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBP]);
 st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ESI]);
 st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDI]);
 st->cr();
 st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EIP]);
 st->print(", CR2=" INTPTR_FORMAT, uc->uc_mcontext.cr2);
 st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
#endif // AMD64
 st->cr();
 st->cr();
 
 intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc);
 st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
 print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));
 st->cr();
 
 // Note: it may be unsafe to inspect memory near pc. For example, pc may
 // point to garbage if entry point in an nmethod is corrupted. Leave
 // this at the end, and hope for the best.
 address pc = os::Linux::ucontext_get_pc(uc);
 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
 print_hex_dump(st, pc - 16, pc + 16, sizeof(char));
}

寄存器的信息在分析出錯的時候是非常重要的

打印出執行附近的部分機器碼

?
1
2
3
4
5
Instructions: (pc=0x00007f48f14ef51a)
0x00007f48f14ef4fa: 90 90 55 48 89 e5 48 81 ec 98 9f 00 00 48 89 bd
0x00007f48f14ef50a: f8 5f ff ff 48 89 b5 f0 5f ff ff b8 00 00 00 00
0x00007f48f14ef51a: c7 00 01 00 00 00 c6 85 00 60 ff ff ff c9 c3 90
0x00007f48f14ef52a: 90 90 90 90 90 90 55 48 89 e5 53 48 8d 1d 94 00

在instruction 部分中會打印出部分的機器碼
格式是

地址:機器碼 

第一種使用udis庫里帶的udcli工具來反匯編

命令:

echo '90 90 55 48 89 e5 48 81 ec 98 9f 00 00 48 89 bd' | udcli -intel -x -64 -o 0x00007f48f14ef4fa 

顯示出對應的匯編

第二種可以用

objectdump -d -C libjvm.so >> jvmsodisass.dump  

查找偏移地址  0x593045, 就是當時的執行的匯編,然后結合上下文,源碼推測出問題的語句。

d.寄存器對應的內存的值

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
RAX=0x0000000000000000 is an unknown value
RBX=0x000000041a07d1e8 is an oop
{method}
 - klass: {other class}
RCX=0x0000000000000000 is an unknown value
RDX=0x0000000040111800 is a thread
RSP=0x0000000041261b88 is pointing into the stack for thread: 0x0000000040111800
RBP=0x000000004126bb20 is pointing into the stack for thread: 0x0000000040111800
RSI=0x000000004126bb80 is pointing into the stack for thread: 0x0000000040111800
RDI=0x00000000401119d0 is an unknown value
R8 =0x0000000040111c40 is an unknown value
R9 =0x00007f48fcc8b550: <offset 0xa85550> in /usr/java/jdk1.6.0_30/jre/lib/amd64/server/libjvm.so at 0x00007f48fc206000
R10=0x00007f48f8ca7d41 is an Interpreter codelet
method entry point (kind = native) [0x00007f48f8ca7ae0, 0x00007f48f8ca8320] 2112 bytes
R11=0x00007f48fc98f270: <offset 0x789270> in /usr/java/jdk1.6.0_30/jre/lib/amd64/server/libjvm.so at 0x00007f48fc206000
R12=0x0000000000000000 is an unknown value
R13=0x000000041a07d1e8 is an oop
{method}
 - klass: {other class}
R14=0x000000004126bb88 is pointing into the stack for thread: 0x0000000040111800
R15=0x0000000040111800 is a thread

jvm 會通過寄存器的值對找對應的對象,也是一個比較好的參考

e. 其他的信息

error 里面還有一些線程信息,還有當時內存映像信息,這些都可以作為分析的部分參考

crash 報告可以大概的反應出一個當時的情況,特別是在沒有core dump的時候,是比較有助于幫助分析的,但如果有core dump的話,最終還是core dump能快速準確的發現問題原因。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持服務器之家!

原文鏈接:http://blog.csdn.net/raintungli/article/details/7642575

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 俺去也亚洲色图 | 久久91精品国产91 | 国产激情一区二区三区成人91 | 国产短视频精品一区二区三区 | 日本一区二区三区在线 视频 | 国产男女爱视频在线观看 | 亚洲26uuuu最新地址 | 青草悠悠视频在线观看 | 精品久久99麻豆蜜桃666 | 日韩色图区 | 极品丝袜乱系列在线阅读 | 色琪琪原网站亚洲香蕉 | 女人c交zzzooo在线观看 | 狠狠干综合网 | 青青草影院在线观看 | 福利片免费一区二区三区 | 性插图动态图无遮挡 | 帅老头恋帅老头同性tv | 午夜在线观看视频 | 免费午夜网站 | 波多野结衣在线中文字幕 | 欧美一级鲁丝片免费看 | 牧教师| 亚洲天堂免费观看 | 欧美高清日韩 | 3d动漫美女被吸乳羞羞视频 | 男人网站视频 | 天堂avav | caoporn国产| 欧美男人的天堂 | 日本xxxxx18护士xxx | 精品一区二区三区五区六区七区 | 国产精品成人网红女主播 | 久久精品无码人妻无码AV蜜臀 | 成人免费观看网欧美片 | 色综合久久中文字幕综合网 | 深夜福利入口 | 女生被草 | 毛片应用 | 久久精品热只有精品 | 91精品国产免费久久国语蜜臀 |