有一次服务器jvm crash,无任何异常信息。后来想想不对啊,除非是人为的将java的进程kill掉,要不然不可能没有错误日志的,后来突然想起上次价格行情做性能测 试时,当jvm crash掉之后,是在Tomcat下生成一个hs_err_pid**.log文件的,于是找到那个文件,下面是分析过程, 这个文件有几部分内容,首先是头部信息,头信息包含了出错的大体信息和位置。
02 |
# A fatal error has been detected by the Java Runtime Environment: |
04 |
# SIGSEGV ( 0xb ) at pc= 0x00002ad9817ab34e , pid= 10344 , tid= 1083357504
|
06 |
# JRE version: 6 .0_18-b07
|
07 |
# Java VM: Java HotSpot(TM) 64 -Bit Server VM ( 16.0 -b13 mixed mode linux-amd64 )
|
09 |
# V [libjvm.so+ 0x2de34e ]
|
11 |
# If you would like to submit a bug report, please visit: |
在这部分中,有三块内容需要我们注意,一是SIGSEGV是一个信号名称,表示这是一个建立CORE文件段的非法错 误; 二是指明了运行环境,jre版本以及jvm版本;三是最重要的信息,它指明了出错的地方,这里V表示一种frame type,这里是指vmframe,而中括号里则表示出错是在libjvm.so这个文件里,具体位置的偏移量为+号后面的数据。由这里可以知道这是由于 jvm自身运行错误导致。
这个文件的第二部分则是当前处理的线程,或者说是当jvm crash时在运行的线程,详细内容如下:
01 |
--------------- T H R E A D --------------- |
03 |
Current thread ( 0x000000005d835000 ): GCTaskThread [stack: 0x000000004082b000 , 0x000000004092c000 ] [id= 10346 ]
|
05 |
siginfo:si_signo=SIGSEGV: si_errno= 0 , si_code= 128 (), si_addr= 0x0000000000000000
|
08 |
RAX= 0x0000000000000001 , RBX= 0x00002aaab9f2bdd0 , RCX= 0x00002aaaaea56eb8 , RDX= 0x000a000d003e0024
|
09 |
RSP= 0x000000004092aed0 , RBP= 0x000000004092aef0 , RSI= 0x00002aaab9f2bdd0 , RDI= 0x000000005d883780
|
10 |
R8 = 0x00002aaaaea56d80 , R9 = 0x0000000000000001 , R10= 0x00002ad981de7201 , R11= 0x00002ad981df46e0
|
11 |
R12= 0x000000005d883780 , R13= 0x00002aaaaea56eb8 , R14= 0x00002aaaaea56eb8 , R15= 0x000000005d883780
|
12 |
RIP= 0x00002ad9817ab34e , EFL= 0x0000000000010202 , CSGSFS= 0x0000000000000033 , ERR= 0x0000000000000000
|
13 |
TRAPNO= 0x000000000000000d
|
15 |
Top of Stack: (sp= 0x000000004092aed0 )
|
16 |
0x000000004092aed0 : 000000004092af00 00002ad9817ab3be
|
17 |
0x000000004092aee0 : 00002aaab9f2bdd0 00002aaab9f2bdd0
|
这里只要第一行即可,这一行指明了,当crash时,程序正在运行垃圾回收线程,所以有理由怀疑是垃圾回收出了问题,然后这个文件就指引我们来到了第三部分,dump出来的线程信息。
01 |
--------------- P R O C E S S --------------- |
02 |
Java Threads: ( => current thread ) |
03 |
0x0000000056523000 JavaThread "Keep-Alive-Timer" daemon [_thread_blocked, id= 12281 ,
|
04 |
stack( 0x00000000478cc000 , 0x00000000479cd000 )]
|
05 |
0x0000000056a2e000 JavaThread "pool-7-thread-3" [_thread_blocked, id= 8876 , stack
|
06 |
( 0x0000000046fc3000 , 0x00000000470c4000 )]
|
07 |
0x000000005687f800 JavaThread "ClientConnectionHandler" daemon [_thread_in_native,
|
08 |
id= 4786 , stack( 0x0000000044599000 , 0x000000004469a000 )]
|
09 |
0x0000000056d0b000 JavaThread "MERGE2.FindSubgroups thread (channel=*******)"
|
10 |
daemon [_thread_blocked, id= 4710 , stack( 0x00000000472c6000 , 0x00000000473c7000 )]
|
11 |
0x0000000056796800 JavaThread "pool-7-thread-2" [_thread_blocked, id= 6325 , stack
|
12 |
( 0x00000000477cb000 , 0x00000000478cc000 )]
|
16 |
PSYoungGen total 160448K, used 154320K [ 0x00002aaac8b60000 , 0x00002aaad2fc0000 ,
|
18 |
eden space 152448K, 100 % used [ 0x00002aaac8b60000 , 0x00002aaad2040000 , 0x00002aaad2040000 )
|
19 |
from space 8000K, 23 % used [ 0x00002aaad27f0000 , 0x00002aaad29c4018 , 0x00002aaad2fc0000 )
|
20 |
to space 7872K, 12 % used [ 0x00002aaad2040000 , 0x00002aaad2134018 , 0x00002aaad27f0000 )
|
21 |
PSOldGen total 349568K, used 344605K [ 0x00002aaab3600000 , 0x00002aaac8b60000 ,
|
23 |
object space 349568K, 98 % used [ 0x00002aaab3600000 , 0x00002aaac8687690 , 0x00002aaac8b60000 )
|
24 |
PSPermGen total 65792K, used 48038K [ 0x00002aaaae200000 , 0x00002aaab2240000 ,
|
26 |
object space 65792K, 73 % used [ 0x00002aaaae200000 , 0x00002aaab10e9bf8 , 0x00002aaab2240000 )
|
30 |
jvm_args: -Xms128m -Xmx512m -XX:PermSize=64m -Djava.net.preferIPv4Stack= true -Drialto.command.port= 6789 -Drialto.work.dir=/home/admin/output/work
|
31 |
java_command: com.******.*****.*****.apptask.CheckTaskStart |
32 |
Launcher Type: SUN_STANDARD |
33 |
Environment Variables: |
34 |
JAVA_HOME=/usr /*****/ java
|
35 |
PATH=/usr /*****/ java/bin:/usr /******/ ant/bin:/usr /******/ antx- 2 /bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/admin/bin
|
36 |
LD_LIBRARY_PATH=/usr /*******/ install/jdk1. 6 .0_18/jre/lib/amd64/server:/usr /******/ install/jdk1. 6 .0_18/jre/lib/amd64:/usr /******/ install/jdk1. 6 .0_18/jre/../lib/amd64
|
在略过上面N行的处于bolcked状态下的线程信 息后,我们终于看到了此时的堆信息。由标红处我们发现,crash正处于eden区达到了100%要进行young gc的时候,因此我们有理由相信是由于young gc出了问题所致。但是什么问题呢?于是上google搜了一下“jvm crash young gc”。good luck!第一篇就找到了相应的解决方法,原来是这是jdk1.6u18的一个bug,官方文档介绍如下:
1 |
Card-Marking Optimization Issue |
2 |
A flaw in the implementation of a card-marking performance optimization in the JVM can cause heap corruption under some circumstances. This issue affects the CMS garbage collector prior to 6u18, and the CMS, G1 and Parallel Garbage Collectors in 6u18. The serial garbage collector is not affected. Applications most likely to be affected by this issue are those that allocate very large objects which would not normally fit in Eden, or those that make extensive use of JNI Critical Sections (JNI Get/Release*Critical).
|
3 |
This issue will be fixed in the next Java SE 6 update.
|
4 |
Meanwhile, as a workaround to the issue, users should disable this performance optimization by -XX:-ReduceInitialCardMarks.
|
这段话主要三个意思:一是指这个bug影响的GC类型为1.6u18前的CMS类GC以及1.6u18的CMS、G1和并行类GC,而串行GC不受影 响;二是指哪些程序会受影响,主要是那些会分配大量的大对象而eden区过小或者对JNI使用比较敏感的程序;三是指明了处理方法
那么此处是否符合前面的两个条件呢?通过JVM参数,我们发现本例中的GC类型未指定,也就是使用的是默认参数,那么默认的GC类型是什么呢?在 JDK5.0之前默认的GC是串行GC,但是之后尤其是到了JDK6.0之后就更加智能化了,会依据机器的性能来进行指定,怎么个指定法呢?有以下三条原 则:
1、如果你是使用服务器类JVM的话,那么就会由并行GC来取代串行GC;
2、当程序运行后,会首先去检查硬件环境,如果确定其性能满足服务器类机器的标准的话,就会运行服务器类JVM
3、什么样的机器符合服务器类的标准呢?CPU至少要在2核以上,物理内存在2G以上。
通过以上三条,可以确认任务机符合服务器类机器的标准,因此会使用并行GC,在这个bug的影响范围内。而对于第二点,JVM参数只指定了512M内存, 除去永久区的64M,而新生代与老生代的默认分配比例是1:8,因此新生代大约是在50M左右,的确不是一个很大的数字。当初也许是由于担心任务和web 跑在一台机器上吧,因此将JVM的堆参数设得这么小。
后续的处理方法一是将任务的JVM参数标准化;二是使用-XX:-ReduceInitialCardMarks来解决这个bug!
参考原文来自:http://blog.csdn.net/hpsysljt/article/details/6388082
分享到:
相关推荐
Java 本身提供了多种丰富的工具来帮助开发人员查看和分析 GC 以及 JVM 内存的状况。 输出GC日志 输出 GC 日志对于跟踪分析 GC 的状况,无疑是最明显和直接的分析内存回收状况的方 法,只是 GC 日志输出后需要人肉的...
java 查看JVM中所有的线程的活动状况 java 查看JVM中所有的线程的活动状况
代码如下:failed to create jvm error code -4 这一般应是内存不够用所致,解决方法参考如下。 打开 Android Studio 安装目录下的bin目录,查找并打开文件 studio.exe.vmoptions,修改代码: 代码如下:-Xmx512m 为...
JVM内存状况查看方法和分析工具,值得借鉴
jvm源码,jvm-native的源码,jvm支行机制,可对jvm的运行过程进行分析 个人网站:https://www.zhangjunbk.com
本篇文章是对jni调用时,jvm的报错问题进行了详细的分析介绍,需要的朋友参考下
jvm gc jvm gc jvm调优 查看工具
本系列课程从JVM基础到高级实战,老师手把手教你如何进行JVM调优,思路清晰,没有废话,旨在挑战高薪。 课程亮点: 1、基于阿里arthas进行JVM调优; 2、基于代码排查OOM问题,拒绝空讲; 3、总结JVM通用的调优思路;...
jvm源码
JVM图解-JVM指令-JVM原型图.rar
jvm 配置jvm参数 配置jvm参数
linux 下用java 获取系统信息 cpu mem jvm等 用java调用系统命令得到,方便实用
EBS R11,打开时IE报错,更新该DLL文件后,文件解决。
深入解析jvm深入解析jvm深入解析jvm深入解析jvm深入解析jvm深入解析jvm
46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT...
主要是JVM内存分配及简单的JVM性能调优
jvm
idea 插件visulgc 监控jvm
一份JVM学习的笔记,含查看JVM运行时信息\JVM垃圾收集信息\JVM锁信息等
学习关于JVM基础,java内模型的全面透析,Jar hell问题以及解决办法,Class文件格式 • Java编译执行流程 • ClassFile的格式介绍 • ClassFile中FieldInfo和MethodInfo介绍 • 类型描述Descriptor介绍 • ClassFile...