jvm crash 分析

今天tomcat的jvm崩了,一直jvm崩掉,每次也就看了一下内存区域,判断大概是内存问题,今天决定好好分析一下,整理了网上的一些资料。 
    
1.crash文件 
     如果有一个严重的错误引起Java进程非正常退出,我们叫Crash,这时候会产生一个日志文件。生成在工作目录下,名字为 hs_err_pidxxxx.log,可以修改配置来改变 
java -XX:ErrorFile=/var/log/java/java_error_%p.log 

其主要原因是card-marking performance optimization算法在实现的时候有瑕疵,在某些情况下会引起heap corruption。这个情况主要发生在新创建的大对象

和Eden space大小差不多,然后jvm做young GC的时候。                                         

解决方案:在启动参数中增加-XX:-ReduceInitialCardMarks将性能优化策略关闭。


2.crash头部 

Java代码   收藏代码
  1. #  
  2. # A fatal error has been detected by the Java Runtime Environment:  
  3. #  
  4. #  SIGSEGV (0xb) at pc=0xb7a0d926, pid=6028, tid=1876777888  
  5. #  
  6. # JRE version: 6.0_18-b07  
  7. # Java VM: Java HotSpot(TM) Server VM (16.0-b13 mixed mode linux-x86 )  
  8. # Problematic frame:  
  9. # V  [libjvm.so+0x5a2926]  
  10. #  
  11. # If you would like to submit a bug report, please visit:  
  12. #   http://java.sun.com/webapps/bugreport/crash.jsp  
  13. #  



   文件头中有很多有用的信息,“EXCEPTION_ACCESS_VIOLATION ”意味着Java应用Crash的时候,正在运行JVM自己的代码,而不是外部的Java代码或其他类库代码。这种情况很可能是JVM的Bug,但是也不一定。除了“EXCEPTION_ACCESS_VIOLATION ”,还有可能是别的信息,例如“SIGSEGV(0xb)”,意味着JVM正在执行本地或JNI的代码;EXCEPTION_STACK_OVERFLOW”意味着这是个栈溢出的错误。 
    另一个有用的就是 

Java代码   收藏代码
  1. # Problematic frame:  
  2. # V  [libjvm.so+0x5a2926]  



它说明Crash的时候,JVM正在从哪个库文件执行代码。除了“V”以外,还有可能是“C”、“j”、“v”、“J”。具体的表示意思如下: 

FrameType Description: 
C: Native C frame 
j: Interpreted Java frame 
V: VMframe 
v: VMgenerated stub frame 
J: Other frame types, including compiled Java frames 

3.线程部分 
  当jvm crash时在运行的线程,详细内容如下 

Java代码   收藏代码
  1. ---------------  T H R E A D  ---------------  
  2.   
  3. Current thread (0x08064800):  GCTaskThread [stack: 0x6fd55000,0x6fdd6000] [id=6038]  
  4.   
  5. siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x0000000c  
  6.   
  7. Registers:  
  8. EAX=0x00000000, EBX=0x9f2807e8, ECX=0x00000008, EDX=0x9f280701  
  9. ESP=0x6fdd4e80, EBP=0x6fdd4ee8, ESI=0x6fdd4f38, EDI=0x00000003  
  10. EIP=0xb7a0d926, CR2=0x0000000c, EFLAGS=0x00010293  
  11.   
  12. Top of Stack: (sp=0x6fdd4e80)  
  13. 0x6fdd4e80:   c5d623b6 01064800 00000001 00000031  
  14. 0x6fdd4e90:   c5d623b7 00000400 6fdd4ed8 b79a803e  
  15. 0x6fdd4ea0:   c5d623b6 00000006 00dd4ee8 9f2807f0  
  16. 0x6fdd4eb0:   00000000 010a5cf0 6fdd4ee8 b777cd6b  
  17. 0x6fdd4ec0:   080b5e40 6fdd4f38 00000af7 00000af7  
  18. 0x6fdd4ed0:   796f1c9e 08060210 00000001 7fd26e00  
  19. 0x6fdd4ee0:   6fdd4f38 00000003 6fdd4f18 b7a0e19e  
  20. 0x6fdd4ef0:   080d5fa8 9f2807e8 00000001 6fdd4f38   
  21.   
  22. Instructions: (pc=0xb7a0d926)  
  23. 0xb7a0d916:   0f 84 3d 02 00 00 c6 45 c3 00 8b 43 04 8d 48 08  
  24. 0xb7a0d926:   8b 51 04 89 d7 c1 ff 02 85 d2 89 7d bc 0f 8e df   
  25.   
  26. Stack: [0x6fd55000,0x6fdd6000],  sp=0x6fdd4e80,  free space=1ff6fdd4814k  
  27. Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)  
  28. V  [libjvm.so+0x5a2926]  
  29. V  [libjvm.so+0x5a319e]  
  30. V  [libjvm.so+0x5a5270]  
  31. V  [libjvm.so+0x324cbb]  
  32. V  [libjvm.so+0x55de9e]  
  33. C  [libpthread.so.0+0x55cc]  



   这里指明了,当crash时,程序正在运行垃圾回收线程,所以有理由怀疑是垃圾回收出了问题,然后是一大堆的blocked的tomcat线程。此处略过 

4.内存状态部分 

Java代码   收藏代码
  1. Heap  
  2.  PSYoungGen      total 7040K, used 6912K [0x9eda00000x9f6900000xb42f0000)  
  3.   eden space 5440K, 100% used [0x9eda0000,0x9f2f0000,0x9f2f0000)  
  4.   from space 1600K, 92% used [0x9f2f0000,0x9f460000,0x9f480000)  
  5.   to   space 1600K, 91% used [0x9f500000,0x9f66c000,0x9f690000)  
  6.  PSOldGen        total 193344K, used 190843K [0x742f00000x7ffc00000x9eda0000)  
  7.   object space 193344K, 98% used [0x742f0000,0x7fd4ee08,0x7ffc0000)  
  8.  PSPermGen       total 16640K, used 16403K [0x702f00000x713300000x742f0000)  
  9.   object space 16640K, 98% used [0x702f0000,0x712f4e48,0x71330000)  



  这里可以看到,crash的时候eden space 100%使用了,有理由怀疑jvm在young gc的时候挂掉了。找了一下问题,最后在官方网站找到这个问题了 
[url]http://www.oracle.com/technetwork/java/javase/6u18-142093.html 
[/url] 
Card-Marking Optimization Issue 
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). 

This issue will be fixed in the next Java SE 6 update. 

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,而且版本是6U18在这个bug的影响范围内。而且我们没有为这个tomcat配置内存,使用默认配置,内存比较小。 
  后续的处理方法 
  一给配置了Xms和Xmx; 
  二是使用-XX:-ReduceInitialCardMarks来解决这个bug。 
   三 是用  -XX:PermSize= 加大存放JVM加载的类型信息的内存 
   现在已经加了,先运行起来再观察。 

扫描二维码关注公众号,回复: 232990 查看本文章

猜你喜欢

转载自yuhuiblog6338999322098842.iteye.com/blog/2366397