2011-12-03 11 views
0

我們有一個運行在JBoss上的基於Web Java的應用程序,允許的最大堆大小約爲2.2 GB(年輕一代爲400MB,機器總計物理內存爲4 GB) 。在某些時候,應用程序停止響應(對客戶端)幾分鐘。經過一番分析,我們發現罪魁禍首是年輕一代GC。下面是詳細GC日誌的摘錄:YGC(ParNew)實時更多用戶+系統時間

Heap before GC invocations=3844 (full 7): 
par new generation total 614336K, used 614272K, eden space 614272K, 100% used, from space 64K, 0% used, to space 64K, 0% used , concurrent mark-sweep generation total 921600K, used 690936K, concurrent-mark-sweep perm gen total 262144K, used 65905K 2679114.965: [GC 2681684.725: [ParNew: 614272K->0K(614336K), 0.0132460 secs] 1305208K->692360K(1535936K), 0.0135020 secs] [Times: user=0.03 sys=0.03, real=2569.62 secs] 
Heap after GC invocations=3845 (full 7): 
par new generation total 614336K, used 0K, eden space 614272K, 0% used, from space 64K, to space 64K, 0% used, concurrent mark-sweep generation total 921600K, used 692360K, concurrent-mark-sweep perm gen total 262144K, used 65905K 
Total time for which application threads were stopped: 2569.7748610 seconds 

什麼我不明白是怎麼回事可能是花在ParNew GC真正的時間是約42分鐘(2569秒),而用戶+ SYS時間只需0.06秒,暫停時間僅爲0.0132460秒。

我們猜測「虛擬存儲器系統顛簸」或「高CPU負荷」可能會導致此問題,我們測試兩種情況:

  1. 我們開始其使用而循環中使用100%的CPU等幾個PROGRAME ,並且GC日誌如下: 6052.217:[GC 6052.217:[ParNew:409288K-> 0K(409536K),1.9456320secs] 480161K-> 72140K(1638336K),1.9460370secs] [Times:user = 0.03 sys = 0.00 ,real = 1.95 secs]

  2. 我們啓動了幾個需要大量內存的progarm,現在GC日誌如下: 11710。 051:[GC 11710.058:[ParNew:409472K-> 0K(409536K),5.9080290秒] 489119K-> 81136K(1638336K),5.9256280秒]

在任何這兩個案例,年輕一代的時間GC變得更長,但小集合的暫停時間與實時大致相同,似乎不是其中任何一個導致長時間停頓。

但所有其他時間去哪裏?

+0

只是一個問題,你用什麼工具來生成以上輸出?或者這是一些alternatvie(非Oracle)JVM?非常感謝。 – eckes

回答

1

在停止世界GC之前,所有線程都必須達到安全點。通常這很快發生,但是一些JNI方法可能會長時間運行而沒有安全點。這是在GC真正開始之前可能需要很長時間的原因之一。

如果您再次看到這一點,這將是值得得到一個C級堆棧跟蹤(在jstack很可能已經進行了GC之後直到響應)

+0

它再次出現。 – lida