2014-04-01 61 views
0

我們在tomcat 7,JDK 7,Amazon Linux中有一個Web應用程序。這是我們對GC配置的要求:Java CMS GC,系統空閒時佔用CPU的GC線程

-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled" 

我們沒有啓用「PrintGCDetails」。

這就是每隔幾秒打印出來的gc.log文件(爲48小時,此時的應用程序在0負載下 - 絕對沒有活動,甚至下面的內容被打印出來並且CPU採取這些線程是15%)(請參閱下面的上下文中):

940568.925: [GC 7425641K(8277888K), 0.2201750 secs] 
940572.415: [GC 7425641K(8277888K), 0.1782950 secs] 
940574.101: [GC 7425641K(8277888K), 0.1736550 secs] 
940577.545: [GC 7425647K(8277888K), 0.1779190 secs] 

而且我們看到,下面的GC線程佔用CPU(約15%的總),即使:

  • 系統中沒有任何活動,
  • 沒有其他線程處於活動狀態,除此之外,此狀態持續48小時,系統此時處於0負載下
  • 系統是0負載下也爲前24小時,然後這些線程變得活躍
  • 當這些線程是活躍的並且佔用CPU,前述系在gc.log
  • 此繼續印刷2天,當我們最終通過在此JVM中調用Web應用程序5分鐘來加載時,然後它全部停止。我們注意到這些線程現在不再需要CPU(他們正在使用< 1%)。這個問題在完成GC發生後似乎已經解決了。完整的GC發生在系統負載後。
  • 簡而言之,當系統處於0負載下48小時時,GC線程繼續佔用15%CPU

這些線程:

"Gang worker#0 (Parallel GC Threads)" prio=10 tid=0x00007fad9402e000 nid=0x629d runnable 
"Gang worker#1 (Parallel GC Threads)" prio=10 tid=0x00007fad94030000 nid=0x629e runnable 
"Gang worker#2 (Parallel GC Threads)" prio=10 tid=0x00007fad94031800 nid=0x629f runnable 
"Gang worker#3 (Parallel GC Threads)" prio=10 tid=0x00007fad94033800 nid=0x62a0 runnable 
"Gang worker#4 (Parallel GC Threads)" prio=10 tid=0x00007fad94035800 nid=0x62a1 runnable 
"Gang worker#5 (Parallel GC Threads)" prio=10 tid=0x00007fad94037000 nid=0x62a2 runnable 
"Gang worker#6 (Parallel GC Threads)" prio=10 tid=0x00007fad94039000 nid=0x62a3 runnable 
"Gang worker#7 (Parallel GC Threads)" prio=10 tid=0x00007fad9403b000 nid=0x62a4 runnable 
"Gang worker#8 (Parallel GC Threads)" prio=10 tid=0x00007fad9403d000 nid=0x62a5 runnable 
"Gang worker#9 (Parallel GC Threads)" prio=10 tid=0x00007fad9403e800 nid=0x62a6 runnable 
"Gang worker#10 (Parallel GC Threads)" prio=10 tid=0x00007fad94040800 nid=0x62a7 runnable 
"Gang worker#11 (Parallel GC Threads)" prio=10 tid=0x00007fad94042800 nid=0x62a8 runnable 
"Gang worker#12 (Parallel GC Threads)" prio=10 tid=0x00007fad94044000 nid=0x62a9 runnable 
"Concurrent Mark-Sweep GC Thread" prio=10 tid=0x00007fad9418b000 nid=0x62ae runnable 
"Gang worker#0 (Parallel CMS Threads)" prio=10 tid=0x00007fad94183000 nid=0x62aa runnable 
"Gang worker#1 (Parallel CMS Threads)" prio=10 tid=0x00007fad94185000 nid=0x62ab runnable 
"Gang worker#2 (Parallel CMS Threads)" prio=10 tid=0x00007fad94187000 nid=0x62ac runnable 
"Gang worker#3 (Parallel CMS Threads)" prio=10 tid=0x00007fad94188800 nid=0x62ad runnable 

問題1:爲什麼會GC日誌中充滿時,這些線程正在以下15%的CPU?

940568.925: [GC 7425641K(8277888K), 0.2201750 secs] 
940572.415: [GC 7425641K(8277888K), 0.1782950 secs] 

問題2:上述日誌是否表明CMS(標記,掃描等)失敗?

問題3:爲什麼當我們在Web應用程序中引入中等負載併發生FULL GC時,它會自行解決?

是的,我會嘗試在啓用printGCDetails的另一個環境中複製問題並返回信息或解決方案 - 如果有人以前看到過這個問題,請添加到對話中。

編輯1:這是日誌時 「PrintGCDetails」 已啓用:

1376.326: [GC [1 CMS-initial-mark: 6481517K(7281088K)] 6536750K(8277888K), 0.0094620 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
1376.336: [CMS-concurrent-mark-start] 
1377.992: [CMS-concurrent-mark: 1.656/1.656 secs] [Times: user=6.62 sys=0.00, real=1.66 secs] 
1377.992: [CMS-concurrent-preclean-start] 
1378.005: [CMS-concurrent-preclean: 0.014/0.014 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 

1378.006: [CMS-concurrent-abortable-preclean-start] 
CMS: abort preclean due to time 1413.110: [CMS-concurrent-abortable-preclean: 4.169/35.104 secs] [Times: user=4.23 sys=0.01, real=35.11 secs] 
1413.111: [GC[YG occupancy: 55233 K (996800 K)]1413.111: [Rescan (parallel) , 0.0154040 secs]1413.126: [weak refs processing, 0.0001380 secs]1413.126: [class unloading, 0.0013450 secs]1413.128: [scrub symbol table, 0.0023140 secs]1413.130: [scrub string table, 0.0004850 secs] [1 CMS-remark: 6481517K(7281088K)] 6536751K(8277888K), 0.0201870 secs] [Times: user=0.20 sys=0.00, real=0.02 secs] 
1413.131: [CMS-concurrent-sweep-start] 
1414.151: [CMS-concurrent-sweep: 1.020/1.020 secs] [Times: user=1.02 sys=0.00, real=1.02 secs] 
1414.151: [CMS-concurrent-reset-start] 
1414.177: [CMS-concurrent-reset: 0.026/0.026 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] 

還要注意:在 「CMSMaxAbortablePrecleanTime」 設置爲35秒。 謝謝。

回答

0

被佔用的堆和可用的堆之間必須有足夠的緩衝區。增加(最大)堆的大小,以便佔用總量的70%解決問題。當算法是CMS時,這是特別重要的。 經驗教訓。

+0

通過佔用堆的大小,您意味着應用程序加載/啓動後或完全GC發生後的大小?謝謝 – Casey

+0

假設已經爲工作流程加載了應用程序並且發生了完整的gc。最初將堆的大小增加到一個較大的值,然後運行工作流並查看堆的增長情況。然後調用完整的gc並查看值。那將是被佔領的堆。嘗試並將堆設置爲佔用堆爲70%左右的值。重複,看看這個問題是否消失。 – Khanna111

0

UseConcMarkSweepGC用於老一代垃圾收集,而您的問題1與年輕一代相關。

爲什麼填滿日誌?因爲這是你的應用程序分配內存的方式。你正在分配很多小的年輕物件。年輕一代中的默認收集器是一個複製收集器(單線程),它是一個完全停止詞收集器。你可以嘗試啓用:-XX:+ UseParNewGC做並行。

關於你提到的第二個問題,它沒有任何關係,在CMS中的錯誤和原因來自點1

你可以讓年輕一代有較大-XX :新尺寸耽誤GC電話。

+0

謝謝尤金。我剛剛編輯過,並用斜體表示,以便更清楚。問題是系統在0負載下連續48小時出現異常的15%的CPU,並且在我們調用tomcat容器中的web應用程序時發現它自己解決,並且看到發生了FULL GC。 – Khanna111

+0

至少在Java版本> 7中默認啓用UseParNewGC。 – Khanna111