当jvm出现致命错误时,会生成一个错误文件 hs_err_pid<pid>.log,其中包括了导致jvm crash的重要信息,可以通过分析该文件定位到导致crash的根源,从而改善以保证系统稳定。当出现crash时,该文件默认会生成到工作目录下,然而可以通过jvm参数指定生成路径(JDK6中引入):

-XX:ErrorFile=./hs_err_pid<pid>.log

该文件包含如下几类关键信息:

  • 日志头文件

  • 导致crash的线程信息

  • 所有线程信息

  • 安全点和锁信息

  • 堆信息

  • 本地代码缓存

  • 编译事件

  • gc相关记录

  • jvm内存映射

  • jvm启动参数

  • 服务器信息

下面用一个crash demo文件逐步解读这些信息,以便大家以后碰到crash时方便分析。

日志头文件

日志头文件包含概要信息,简述了导致crash的原因。而导致crash的原因很多,常见的原因有jvm自身的bug,应用程序错误,jvm参数配置不当,服务器资源不足,jni调用错误等。

现在参考下如下描述:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fb8b18fdc6c, pid=191899, tid=140417770411776
#
# JRE version: Java(TM) SE Runtime Environment (7.0_55-b13) (build 1.7.0_55-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.55-b03 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# J  org.apache.http.impl.cookie.BestMatchSpec.formatCookies(Ljava/util/List;)Ljava/util/List;
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

这里一个重要信息是“SIGSEGV(0xb)”表示jvm crash时正在执行jni代码,而不是在执行java或者jvm的代码,如果没有在应用程序里手动调用jni代码,那么很可能是JIT动态编译时导致的该错误。其中SIGSEGV是信号名称,0xb是信号码,pc=0x00007fb8b18fdc6c指的是程序计数器的值,pid=191899是进程号,tid=140417770411776是线程号。

PS:除了“SIGSEGV(0xb)”以外,常见的描述还有“EXCEPTION_ACCESS_VIOLATION”,该描述表示jvm crash时正在执行jvm自身的代码,这往往是因为jvm的bug导致的crash;另一种常见的描述是“EXCEPTION_STACK_OVERFLOW”,该描述表示这是个栈溢出导致的错误,这往往是应用程序中存在深层递归导致的。

还有一个重要信息是:

# Problematic frame:

# J org.apache.http.impl.cookie.BestMatchSpec.formatCookies(Ljava/util/List;)Ljava/util/List;

这表示出现crash时jvm正在执行的代码,这里的“J”表示正在执行java代码,后面的表示执行的方法栈。除了“J”外,还有可能是“C”、“j”、“V”、“v”,它们分别表示:

  • C: Native C frame

  • j: Interpreted Java frame

  • V: VMframe

  • v: VMgenerated stub frame

  • J: Other frame types, including compiled Java frames

加上前面对SIGSEGV(0xb)”的分析,现在可以断定是JIT动态编译导致的该错误。

查阅资料发现:

此异常是由于jdk JIT compiler optimization 导致,bug id 8021898,官网描述如下:

The JIT compiler optimization leads to a SIGSEGV or an NullPointerException at a place it must not happen.

jdk1.7.0_25到1.7.0_55这几个版本都存在此bug,1.7.0_60后修复。可通过升级jdk解决此异常,可参考 http://bugs.java.com/view_bug.do?bug_id=8021898

到这里该问题已经分析出原因了,但是咱们可以再深入一步,分析下其它信息。

导致crash的线程信息

文件下面是导致crash的线程信息和该线程栈信息,描述信息如下:

Current thread (0x00007fb7b4014800):  JavaThread "catalina-exec-251" daemon [_thread_in_Java, id=205044, stack(0x00007fb58f435000,0x00007fb58f536000)]

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

以上表示导致出错的线程是0x00007fb7b4014800(指针),线程类型是JavaThread,JavaThread表示执行的是java线程,关于该线程其它类型还可能是:

  • VMThread:jvm的内部线程

  • CompilerThread:用来调用JITing,实时编译装卸class 。 通常,jvm会启动多个线程来处理这部分工作,线程名称后面的数字也会累加,例如:CompilerThread1

  • GCTaskThread:执行gc的线程

  • WatcherThread:jvm周期性任务调度的线程,是一个单例对象。 该线程在JVM内使用得比较频繁,比如:定期的内存监控、JVM运行状况监控,还有我们经常需要去执行一些jstat 这类命令查看gc的情况

  • ConcurrentMarkSweepThread:jvm在进行CMS GC的时候,会创建一个该线程去进行GC,该线程被创建的同时会创建一个SurrogateLockerThread(简称SLT)线程并且启动它,SLT启动之后,处于等待阶段。CMST开始GC时,会发一个消息给SLT让它去获取Java层Reference对象的全局锁:Lock

后面的"catalina-exec-251"表示线程名,带有catalina前缀的线程一般是tomcat启动的线程,“daemon”表示该线程为守护线程,再后面的“[_thread_in_Java”表示线程正在执行解释或者编译后的Java代码,关于该描述其它类型还可能是:

  • _thread_in_native:线程当前状态

  • _thread_uninitialized:线程还没有创建,它只在内存原因崩溃的时候才出现

  • _thread_new:线程已经被创建,但是还没有启动

  • _thread_in_native:线程正在执行本地代码,一般这种情况很可能是本地代码有问题

  • _thread_in_vm:线程正在执行虚拟机代码

  • _thread_in_Java:线程正在执行解释或者编译后的Java代码

  • _thread_blocked:线程处于阻塞状态

  • …_trans:以_trans结尾,线程正处于要切换到其它状态的中间状态

最后的“id=205044”表示线程ID,stack(0x00007fb58f435000,0x00007fb58f536000)表示栈区间。

“siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x0000003f96dc9c6c”这部分是导致虚拟机终止的非预期的信号信息:其中si_errno和si_code是Linux下用来鉴别异常的,Windows下是一个ExceptionCode。

所有线程信息

再下面是线程信息:

Java Threads: ( => current thread )
  0x00007fb798015800 JavaThread "catalina-exec-280" daemon [_thread_blocked, id=206093, stack(0x00007fb58d718000,0x00007fb58d819000)]
  0x00007fb7a4016800 JavaThread "catalina-exec-279" daemon [_thread_blocked, id=206091, stack(0x00007fb58d819000,0x00007fb58d91a000)]
  ... ...(省略)
  
  Other Threads:
  0x00007fb8b4231000 VMThread [stack: 0x00007fb854eb6000,0x00007fb854fb7000] [id=192015]
  0x00007fb8b4321000 WatcherThread [stack: 0x00007fb835e6c000,0x00007fb835f6d000] [id=192414]

信息和上面介绍的类似,其中[_thread_blocked表示线程阻塞。

安全点和锁信息

再下面是安全点和锁信息:

VM state:not at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread: None

安全线信息为正常运行,其它可能得描述还有:

  • not at a safepoint:正常运行状态

  • at safepoint:所有线程都因为虚拟机等待状态而阻塞,等待一个虚拟机操作完成

  • synchronizing:一个特殊的虚拟机操作,要求虚拟机内的其它线程保持等待状态

锁信息为未被线程持有,Mutex是虚拟机内部的锁,而Monitor则是synchronized锁或者其它关联到的Java对象。

堆信息

再下面是堆信息:

Heap
 par new generation   total 2293760K, used 1537284K [0x00000006f0000000, 0x0000000790000000, 0x0000000790000000)
  eden space 1966080K,  78% used [0x00000006f0000000, 0x000000074dc97aa8, 0x0000000768000000)
  from space 327680K,   0% used [0x0000000768000000, 0x00000007680a9580, 0x000000077c000000)
  to   space 327680K,   0% used [0x000000077c000000, 0x000000077c000000, 0x0000000790000000)
 concurrent mark-sweep generation total 1572864K, used 49449K [0x0000000790000000, 0x00000007f0000000, 0x00000007f0000000)
 concurrent-mark-sweep perm gen total 262144K, used 49857K [0x00000007f0000000, 0x0000000800000000, 0x0000000800000000)
 
 Card table byte_map: [0x00007fb8b8fa8000,0x00007fb8b9829000] byte_map_base: 0x00007fb8b5828000

堆信息包括:新生代、老生代、永久代信息。这里标识了使用CMS垃圾收集器。

下面的“Card table”表示一种卡表,是jvm维护的一种数据结构,用于记录更改对象时的引用,以便gc时遍历更少的table和root。

本地代码缓存

再下面是本地代码缓存信息:

Code Cache  [0x00007fb8b1000000, 0x00007fb8b1a60000, 0x00007fb8b4000000)
 total_blobs=3580 nmethods=3111 adapters=421 free_code_cache=38857Kb largest_free_block=39469312

这是一块用于编译和保存本地代码的内存;注意是本地代码,它和PermGen(永久代)是不一样的,永久代是用来存放jvm和java类的元数据的。

编译事件

再下面是本地代码编译信息:

Compilation events (10 events):
Event: 110587.798 Thread 0x00007fb8b425a800 3338             java.util.HashSet::remove (20 bytes)
Event: 110587.804 Thread 0x00007fb8b425a800 nmethod 3338 0x00007fb8b168a9d0 code [0x00007fb8b168ab60, 0x00007fb8b168afa8]
... ...(省略)
Event: 112147.387 Thread 0x00007fb8b425a800 3342             org.apache.http.impl.cookie.BestMatchSpec::formatCookies (116 bytes)
Event: 112147.465 Thread 0x00007fb8b425a800 nmethod 3342 0x00007fb8b18fcd50 code [0x00007fb8b18fd1a0, 0x00007fb8b18ff338]

可以看到,一共编译了10次;其中包含org.apache.http.impl.cookie.BestMatchSpec::formatCookies的编译;这和前面的结论相吻合。

gc相关记录

再下面是gc执行记录:

GC Heap History (10 events):
Event: 110665.975 GC heap before
{Heap before GC invocations=255 (full 31):
 par new generation   total 2293760K, used 1966777K [0x00000006f0000000, 0x0000000790000000, 0x0000000790000000)
  eden space 1966080K, 100% used [0x00000006f0000000, 0x0000000768000000, 0x0000000768000000)
  from space 327680K,   0% used [0x0000000768000000, 0x00000007680ae480, 0x000000077c000000)
  to   space 327680K,   0% used [0x000000077c000000, 0x000000077c000000, 0x0000000790000000)
 concurrent mark-sweep generation total 1572864K, used 49237K [0x0000000790000000, 0x00000007f0000000, 0x00000007f0000000)
 concurrent-mark-sweep perm gen total 262144K, used 49856K [0x00000007f0000000, 0x0000000800000000, 0x0000000800000000)
Event: 110665.981 GC heap after
Heap after GC invocations=256 (full 31):
 par new generation   total 2293760K, used 693K [0x00000006f0000000, 0x0000000790000000, 0x0000000790000000)
  eden space 1966080K,   0% used [0x00000006f0000000, 0x00000006f0000000, 0x0000000768000000)
  from space 327680K,   0% used [0x000000077c000000, 0x000000077c0ad6f8, 0x0000000790000000)
  to   space 327680K,   0% used [0x0000000768000000, 0x0000000768000000, 0x000000077c000000)
 concurrent mark-sweep generation total 1572864K, used 49237K [0x0000000790000000, 0x00000007f0000000, 0x00000007f0000000)
 concurrent-mark-sweep perm gen total 262144K, used 49856K [0x00000007f0000000, 0x0000000800000000, 0x0000000800000000)
}
... ...(省略)

可以看到gc次数为10次(full gc),然后后面描述了每次gc前后的内存信息;看一看到并没有内存不足等问题。

jvm内存映射

再下面是jvm加载的库信息:

Dynamic libraries:
00400000-00401000 r-xp 00000000 08:02 39454583                           /home/service/jdk1.7.0_55/bin/java
00600000-00601000 rw-p 00000000 08:02 39454583                           /home/service/jdk1.7.0_55/bin/java
013cd000-013ee000 rw-p 00000000 00:00 0                                  [heap]
6f0000000-800000000 rw-p 00000000 00:00 0 
3056400000-3056416000 r-xp 00000000 08:02 57409539                       /lib64/libgcc_s-4.4.7-20120601.so.1
3056416000-3056615000 ---p 00016000 08:02 57409539                       /lib64/libgcc_s-4.4.7-20120601.so.1
3056615000-3056616000 rw-p 00015000 08:02 57409539                       /lib64/libgcc_s-4.4.7-20120601.so.1
353be00000-353be20000 r-xp 00000000 08:02 57409933                       /lib64/ld-2.12.so
353c01f000-353c020000 r--p 0001f000 08:02 57409933                       /lib64/ld-2.12.so
353c020000-353c021000 rw-p 00020000 08:02 57409933                       /lib64/ld-2.12.so
... ...(省略)

这些信息是虚拟机崩溃时的虚拟内存列表区域。它可以告诉你崩溃原因时哪些类库正在被使用,位置在哪里,还有堆栈和守护页信息。以列表中第一条为例介绍下:

  • 00400000-00401000:内存区域

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

  • 00000000:文件内的偏移量

  • 08:02:文件位置的majorID和minorID

  • 39454583:索引节点号

  • /home/service/jdk1.7.0_55/bin/java:文件位置

jvm启动参数

再下面是jvm启动参数信息:

VM Arguments:
jvm_args: -Djava.util.logging.config.file=/home/service/tomcat7007-account-web/conf/logging.properties -Xmx4096m -Xms4096m -Xmn2560m -XX:SurvivorRatio=6 -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:/home/work/webdata/logs/tomcat7007-account-web/develop/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/work/webdata/logs/tomcat7007-account-web/develop/ -Dtomcatlogdir=/home/work/webdata/logs/tomcat7007-account-web/develop -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7407 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.endorsed.dirs=/home/service/tomcat7007-account-web/endorsed -Dcatalina.base=/home/service/tomcat7007-account-web -Dcatalina.home=/home/service/tomcat7007-account-web -Djava.io.tmpdir=/home/service/tomcat7007-account-web/temp 
java_command: org.apache.catalina.startup.Bootstrap start
Launcher Type: SUN_STANDARD Environment Variables:
JAVA_HOME=/home/service/jdk1.7.0_55
PATH=/opt/zabbix/bin:/opt/zabbix/sbin:/home/service/jdk1.7.0_55/bin:/home/work/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/work/bin
SHELL=/bin/bash

上面是jvm参数,下面是系统的环境配置。

服务器信息

再下面是服务器信息:

/proc/meminfo:
MemTotal:       65916492 kB
MemFree:        14593468 kB
Buffers:          222452 kB
Cached:         28502452 kB
SwapTotal:             0 kB
SwapFree:              0 kB
... ...(省略)
/proc/cpuinfo:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 62
model name : Intel(R) Xeon(R) CPU E5-2420 v2 @ 2.20GHz
stepping : 4
... ...(省略)

上面是内存信息,主要关注下swap信息,看看有没有使用虚拟内存;下面是cpu信息。

JVM致命错误日志(hs_err_pid.log)分析的更多相关文章

  1. JVM致命错误日志(hs_err_pid.log)分析(转载)

    当jvm出现致命错误时,会生成一个错误文件 hs_err_pid<pid>.log,其中包括了导致jvm crash的重要信息,可以通过分析该文件定位到导致crash的根源,从而改善以保证 ...

  2. JVM致命错误日志(hs_err_pid.log)解读

    JVM致命错误日志(hs_err_pid.log)解读 摘自:https://blog.csdn.net/u013938484/article/details/51811400 2016年07月02日 ...

  3. JVM致命错误日志详解

    目录 文件描述 文件位置 文件头 错误信息记录 JVM运行信息 崩溃原因 错误信息 线程描述 线程信息 信号信息 计数器信息 机器指令 内存映射信息 线程堆栈 其他信息 进程描述 线程列表 虚拟机状态 ...

  4. 详细分析MySQL事务日志(redo log和undo log)

    innodb事务日志包括redo log和undo log.redo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作. undo log不是redo log的逆向过程,其实它 ...

  5. 详细分析MySQL事务日志(redo log和undo log) 表明了为何mysql不会丢数据

    innodb事务日志包括redo log和undo log.redo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作. undo log不是redo log的逆向过程,其实它 ...

  6. 【PHP】善用php-fpm的慢执行日志slow log,分析php性能问题

    (转)善用php-fpm的慢执行日志slow log,分析php性能问题  众所周知,mysql有slow query log,根据慢查询日志,我们可以知道那些sql语句有性能问题.作为mysql的好 ...

  7. 【MySQL (六) | 详细分析MySQL事务日志redo log】

    Reference:  https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html 引言 为了最大程度避免数据写入时 IO ...

  8. jvm系列(九):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  9. hadoop实战 -- 网站日志KPI指标分析

    本项目分析apache服务器产生的日志,分析pv.独立ip数和跳出率等指标.其实这些指标在第三方系统中都可以检测到,在生产环境中通常用来分析用户交易等核心数据,此处只是用于演示说明日志数据的分析流程. ...

随机推荐

  1. es6基础(4)--字符串扩展

    //字符串扩展 { console.log('a','\u0061'); console.log('s','\u20BB7');//超过了0xffff console.log('s','\u{20BB ...

  2. update 中实现子查询

    mysql 在update中实现子查询的方式   当使用mysql条件更新时--最先让人想到的写法 UPDATE buyer SET is_seller=1 WHERE uid IN (SELECT  ...

  3. netfilter/iptables

    参考:tcp/ip协议 1.Linux框架概念 1.1.工作流程图 1.2.功能: ①过滤(filter) ②修改源ip.目标ip(nat) ③拆解报文.修改报文标记.重新封装(mangle) ④关闭 ...

  4. [UGUI]滑动列表优化(循环利用)

    需要注意的有下面几点: 1. 区分好表现上的index和逻辑上的index.表现上的index是指这个go是go列表中的第几项,但实际上这个index的意义并不大,因为在滚动的过程中go列表是轮转的: ...

  5. 使用Fiddler获取手机app数据

    参考资料:https://www.jianshu.com/p/9e05a2522758 Fiddler下载地址   https://www.telerik.com/download/fiddler

  6. RHEL yum

    一.YUM源配置 使用RHEL自带的yum时会显示 #This system is not registered to Red Hat Subscription Management. You can ...

  7. 26.纯 CSS创作按钮被从纸上掀起的立体效果

    原文地址:https://segmentfault.com/a/1190000014930183 感想:主要2D和3D转换.阴影效果. HTML代码: <nav> <ul> & ...

  8. nodejs操作monggodb数据库封装

    var MongoClient=require('mongodb').MongoClient; var DbUrl='mongodb://localhost:27017/productmanage'; ...

  9. RAD Tokyo 10.2.2

    TDialogService类 如果您是使用比较新的RAD Studio版本. 那么您应该开始改用FMX.DialogService程序单元中TDialogService类别的类别方法来取代以前的Me ...

  10. IIS快捷方式

    一般打开IIS管理器的方式 都是 计算机->管理->服务应用程序->Internet应用程序管理器 这样一步就可以 打开IIS了