JVM coredump

JVM crash分析

Java程序运行的时候,遇到了coredump的现象。最后定位到时JIT导致的bug。

http://www.oracle.com/technetwork/java/javase/crashes-137240.html#gbyzu

这里记录下JVMcrash产生的文件怎么去定位问题,但是一般不会遇到crash,hotspot被这么多太机器天天跑,很显眼的问题早被sun修复了。如果你想让JVM挂掉这里提供一个方法:

1.执行ulimit -c unlimited, 这个命令是打开系统对coredump的限制,搞过C++的同学是不是很讨厌这个东西。

2.执行一个JavaTest程序, 让程序sleep一段时间

3.Kill -11 pid,这里给java程序发送了一个SIGSEGV信号,他会以为自己挂了,产生coredump。

JVM挂掉之后产了两个文件,hs_err_pid.log, coredump。hs_err_pid.log基本就是对coredump的描述文件。先看看coredump里面的东西,后面在介绍log文件。Coredump文件需要用gdb去调试,执行命令: gdb -c core java,之后的场景是这样的

是不是很奇怪,kill发送的是SIGSEGV信号,为什么程序是挂载了SIGART上面呢。这是因为JVM扑捉了11这个信号,保留当前的场景,就是你上面看到的hs_err_pid.log这个文件。所以这个文件记录的是那个栈帧的场景,不要直接拿coredump当前栈帧去对照log,你会对不上的。不信的话,infoframe看下rip寄存器和log文件里面的是否一样。这里需要跳到#7栈帧(看上图左边的序号),才是程序挂掉当时的场景。执行f 7之后,再看看info frame,已经和log里面的记录一样了。

下面就解说下log里面到底记录了什么。

日志文件开头就告诉你,JVM是SIGSEGV这个信号的锅,pc是程序计数器,本来指向下一条要执行的指令地址,coredump里面其实就变为执行出问题的那条指令。pid大家都知道,tid是线程id,gdb调试输入命令thread就得到如下

可以看到当前线程号,就是log文件里面记录的线程号。这里插一句,linux里面没有线程这个东西,是LWP模拟的,所以后面有个LWP的进程号,大家用的pthread_create都是glibc模拟出来的东西,操作系统只有fork和clone接口来创建进程。

日志文件的第二部分是进程的挂掉当时的寄存器和栈顶部数据。如下图

途中si_signo表示信号,si_code表示信号产生的用户,uid表示用户id。如上面所说,gdb退回到7号栈帧之后展现的内容和日志文件是一样的(看下图)。寄存器可以用info r命令,看所有寄存器的值。下面栈中的值,可以用RSP栈顶指针指向的地址执行命令:x /8 0x7ffef7302130,得到的结果就是日志里面的值。

接着看日志文件下面的值,如下图:instruction表示指令PC计数器指向的地址有哪些指令,是不是想看看挂掉时候都执行了哪些指令:disassemble 0x00007f95c533d98b这条执行会把指令地址中二进制数据转换为汇编指令,并且把整个函数的指令都翻译出来,带有=>标记的那一行,就是当前执行的指令。接下来Register to memory mapping是把寄存器所指向的内存都解析成字符串,解析不了的,就是unkown了。Stack表示栈内容,Native表示本地方法,而不是Java栈,C表示C代码。

接下来Heap显示的是JVM的堆内存结构,和jmap –heap的结果类型

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值