JVM的hs_err_pid.log的解读

当jvm挂掉的时候。jvm会生成一个带有hs_err_pid.log这样的文件。pid后面跟着的是当前虚拟机的进程id。

在这个文件中,我们往往能够查看到虚拟机挂掉的很多重要信息。所以学会如何分析hs_err_pid文件将能够提高我们定位问题的能力。

也可以通过 java -XX: ErrorFile = /var/log/java/java_error&p.log  的参数进行指定。

这个文件主要分为以下内容:

1、触发知名错误的操作异常或信号;

2、版本和配置信息;

3、触发致命异常的线程详细信息和线程栈;

4、当前运行的线程列表和状态;

5、堆信息;

6、加载的本地动态库信息(或so);

7、命令行参数;

8、环境变量;

9、操作系统的详细信息以及cpu信息。

 

接下来我们根据此文件进行逐段分析。

hs_err_pid12252.log

 

一个虚拟机的非预期的错误被JRE检查到,其中:

SIGSEGV 是信号名称

0xb 是信号码

pc=0x00007f8076a3ffee指的是程序计数器的值

pid=12252 指进程号

pc=0x00007f8076a3ffee 指的是线程号

 

文件头中有很多有用的信息,“EXCEPTION_ACCESS_VIOLATION ”意味着Java应用Crash的时候,正在运行JVM自己的代码,而不是外部的Java代码或其他类库代码。

这种情况很可能是JVM的Bug,但是也不一定。除了“EXCEPTION_ACCESS_VIOLATION ”,还有可能是别的信息,例如“SIGSEGV(0xb)”,意味着JVM正在执行本地或JNI的代码;“EXCEPTION_STACK_OVERFLOW”意味着这是个栈溢出的错误。

 

这里是jre和java 虚拟机的版本信息以及运行环境。

 

这里是出现问题的问题帧。最下面一行是需要进行coredump时(C/C++语言)产生coredump文件需要执行的操作,(这部分之后我会再研究一下。不太清楚c的分析过程)。

C:是本地帧类型

帧的类型包括:

1、C:本地帧

2、j :解释的java帧

3、V(大写):虚拟机帧

4、v (小写):虚拟机生成的存根栈帧

5、J (大写) :其它帧类型,包括编译后的java帧

6、[libdhnetsdk.so+0xf50fee : 和程序计数器(pc)表达的含义一样,但是用的是本地so库+偏移量的方法。

 

0x00007f80a9aa5800  线程指针

javaThread 是线程的类型,这里明显的表达是java线程:

其它类型:

  • JavaThread
  • VMThread
  • CompilerThread
  • GCTaskThread
  • WatcherThread
  • ConcurrentMarkSweepThread

SimpleAsyncTaskExecutor-2 :线程名

  • _thread_in_native:线程当前状态,状态枚举包括:
  • _thread_uninitialized:线程还没有创建,它只在内存原因崩溃的时候才出现
  • _thread_new:线程已经被创建,但是还没有启动
  • _thread_in_native:线程正在执行本地代码,一般这种情况很可能是本地代码有问题
  • _thread_in_vm:线程正在执行虚拟机代码
  • _thread_in_Java:线程正在执行解释或者编译后的Java代码
  • _thread_blocked:线程处于阻塞状态
  • …_trans:以_trans结尾,线程正处于要切换到其它状态的中间状态

id =12617 :线程id

0x00007f80855a8000,0x00007f80856a9000 : 线程栈区间

 

这部分是导致虚拟机终止的非预期的信号信息,含义前面已经大致提到过了。其中si_errno和si_code是Linux下用来鉴别异常的,Windows下是一个ExceptionCode。

这是寄存器的上下文。


栈顶程序计数器旁的操作码,它们可以被反汇编成系统崩溃前执行的指令。(我只拷贝的一部分)


寄存器和内存映射信息。


线程栈。包含了地址、栈顶、栈计数器和线程尚未使用的栈信息,由于栈可能非常长,打印的长度有限制,


但是至少本地栈和Java栈都打印出来了(很多时候本地栈打印不出来,但是Java栈一般都能打印出来)。


线程信息,就不赘述了。


 

虚拟机状态。包括:

 

  • not at a safepoint:正常运行状态;
  • at safepoint:所有线程都因为虚拟机等待状态而阻塞,等待一个虚拟机操作完成;
  • synchronizing:一个特殊的虚拟机操作,要求虚拟机内的其它线程保持等待状态。

虚拟机的Mutex和Monitor目前没有被线程持有。Mutex是虚拟机内部的锁,而Monitor则关联到了Java对象。


接下来的一些信息是关于堆信息。新生代、老生代、永久代。对JVM有了解的人应该都清楚,不解释了。


内存映射。这些信息是虚拟机崩溃时的虚拟内存列表区域。在定位崩溃原因的时候,它可以告诉你哪些类库正在被使用,位置在哪里,还有堆栈和守护页信息。

00400000-00401000 :内存区域

r-xp :权限,r/w/x/p/s分别表示读/写/执行/私有/共享

00000000:文件内的偏移量

fd:00:文件位置的majorID和minorID

68351097:索引节点号

/usr/java/jdk1.8.0_162/jre/bin/java:文件位置

每一个lib都有两块虚拟内存区域——代码和数据,它们的权限不同,代码区域是r-xp;数据区域是rwxp。守护页(guard page)由权限为–xp和rwxp的一对组成。

虚拟机参数和环境变量。


信号句柄。对于Linux下的信号机制,请自行百度。

代码缓存(Code Cache)。这是一块用于编译和保存本地代码的内存,注意是本地代码,它和PermGen(永久代)是不一样的,永久带是用来存放Java类定义的。

最后是系统信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值