• 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的结果类型

  • 相关阅读:
    您的企业从在线直播中可以获益的4种方式
    【系统性学习】Linux Shell常用命令
    打造基于ILRuntime热更新的组件化开发
    低照度图像数据集
    利用适配器模式使用第三方库
    [RoarCTF 2019]PHPShe
    day51
    Win32 简单日志实现
    Linux虚拟机安装Redis
    目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】3D视觉
  • 原文地址:https://blog.csdn.net/m0_67402125/article/details/126409540