追查JVM崩溃

 

JDK升级到1.6后,服务器集群经常崩溃,后来把VM的参数调整为如下:

-Xmx2g -Xms2g -Xmn512m -XX:PermSize=196m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70

指明了最大内存是2G,新生代为512M,年老区196M,内存占用率在达到70%的时候要执行GC,同时要使用CMS方式收集。

 

在增加内存后还是经常挂掉,又不知道具体由什么原因引起,很苦恼。后来就收集fatal log,经过统计,超过90%都是由于同一个因素引起。

 

JVM退出时的错误日志hs_err*.log通常是:

# An unexpected error has been detected by Java Runtime Environment:

#

#  SIGSEGV (0xb) at pc=0x00002ad49843ae5d, pid=986, tid=1102739776

#

# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.0-b16 mixed mode linux-amd64)

# Problematic frame:

# V  [libjvm.so+0x25ee5d]

 

 

Heap

 par new generation   total 471872K, used 166068K [0x00002aaaae200000, 0x00002aaace200000, 0x00002aaace200000)

  eden space 419456K,  33% used [0x00002aaaae200000, 0x00002aaab6bbd590, 0x00002aaac7ba0000)

  from space 52416K,  48% used [0x00002aaac7ba0000, 0x00002aaac9442200, 0x00002aaacaed0000)

  to   space 52416K,   0% used [0x00002aaacaed0000, 0x00002aaacaed0000, 0x00002aaace200000)

 concurrent mark-sweep generation total 1572864K, used 1105061K [0x00002aaace200000, 0x00002aab2e200000, 0x00002aab2e200000)

 concurrent-mark-sweep perm gen total 200704K, used 124029K [0x00002aab2e200000, 0x00002aab3a600000, 0x00002aab3a600000)

 

 

可以看到年老区占用率刚好是1103473/1572864=70%,这个时刻,eden,fromto区都有一个不小的数值,这个说明这个时刻处于GC开始的阶段。后来把libjvm.so反汇编后,得到引起崩溃的执行代码,印证了这个想法。

V  [libjvm.so+0x25ee5d]:       41 ff 95 50 02 00 00    callq  *0x250(%r13)

V  [libjvm.so+0x25ec73]:       e9 7b ff ff ff          jmpq   25ebf3 <_ZN24Par_MarkFromRootsClosure6do_bitEm+0x23>

V  [libjvm.so+0x1cee10]:       49 8b 16                mov    (%r14),%rdx

V  [libjvm.so+0x256209]:       e9 d2 fd ff ff          jmpq   255fe0 <_ZN18CMSConcMarkingTask16do_scan_and_markEiP24CompactibleFreeListSpace+0x60>

V  [libjvm.so+0x255d19]:       4c 89 ef                mov    %r13,%rdi

V  [libjvm.so+0x611f57]:       80 7d a8 01             cmpb   $0x1,-0x58(%rbp)

V  [libjvm.so+0x60f5d4]:       48 8b 5d f8             mov    -0x8(%rbp),%rbx

V  [libjvm.so+0x4e2f6a]:       e9 63 ff ff ff          jmpq   4e2ed2 <_Z10java_startP6Thread+0xb2>

 

 

看得出,在GC线程要标志活的根对象的代码时,退出了。但是我们不知道它具体在做什么。

 

CMSGC的过程:

1)  挂起JVM,这个过程非常短暂,标志所有的从全局变量,堆栈和寄存器可以访问到的对象,这些对象将作为根对象。

2)  恢复JVM的执行后,进行并行多CPU的标志被根对象间接引用到的对象,这个过程不能保证最后得到的结果是正确的,因为同时还有可能有创建新对象或者更新了Java引用了。这些变化同时也被记录下来了。

3)  如果最终可被标志的对象不超过98%,那么再次挂起JVM做最后一次标志。从根对象开始,根据2)记录的变化再次标志。这样就保证不会有对象漏掉了。

4)  恢复JVM,做扫除,把无法访问到对象占用有内存回收。

还有可能做内存整理,把空的内存统一到一块。

 

到了这里,应该可以确定十成九是JVM自身的BUG引起的了。除了自己要尝试升级JDK,还有就是向SUNBUG了。

 

 

参考:

http://java.sun.com/javase/6/webnotes/trouble/TSG-Desktop/html/felog.html

你可能感兴趣的:(jvm,jdk,cms,linux,velocity)