2025-02-10

01 #
02 # A fatal error has been detected by the Java Runtime Environment:
03 #
04 #  SIGSEGV (0xb) at pc=0x00002ad9817ab34e, pid=10344, tid=1083357504
05 #
06 # JRE version: 6.0_18-b07
07 # Java VM: Java HotSpot(TM) 64-Bit Server VM (16.0-b13 mixed mode linux-amd64 )
08 # Problematic frame:
09 # V  [libjvm.so+0x2de34e]
10 #
11 # If you would like to submit a bug report, please visit:
12 #   jsp”>http://java.sun.com/webapps/bugreport/crash.jsp
13 #
     在這部分中,有三塊內容需要我們註意,一是SIGSEGV是一個信號名稱,表示這是一個建立CORE文件段的非法錯 誤; 二是指明瞭運行環境,jre版本以及jvm版本;三是最重要的信息,它指明瞭出錯的地方,這裡V表示一種frame type,這裡是指vmframe,而中括號裡則表示出錯是在libjvm.so這個文件裡,具體位置的偏移量為+號後面的數據。由這裡可以知道這是由於 jvm自身運行錯誤導致。
     這個文件的第二部分則是當前處理的線程,或者說是當jvm crash時在運行的線程,詳細內容如下:
01 —————  T H R E A D  —————
02  
03 Current thread (0x000000005d835000):  GCTaskThread [stack: 0x000000004082b000,0x000000004092c000] [id=10346]
04
05 siginfo:si_signo=SIGSEGV: si_errno=0, si_code=128 (), si_addr=0x0000000000000000
06
07 Registers:
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
14  
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)]
13   
14 ……以下省略N行
15 Heap
16  PSYoungGen      total 160448K, used 154320K [0x00002aaac8b60000, 0x00002aaad2fc0000, 
17 0x00002aaad3600000)
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, 
22 0x00002aaac8b60000)
23   object space 349568K, 98% used [0x00002aaab3600000,0x00002aaac8687690,0x00002aaac8b60000)
24  PSPermGen       total 65792K, used 48038K [0x00002aaaae200000, 0x00002aaab2240000, 
25 0x00002aaab3600000)
26   object space 65792K, 73% used [0x00002aaaae200000,0x00002aaab10e9bf8,0x00002aaab2240000) 
27   
28 ……以下再省略N行
29 VM Arguments:
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
37 SHELL=/bin/bash
在略過上面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!

作者“ERDP技術架構”

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *