2013-10-02 21 views
0

我不確定這是否有一個通用的答案,但我想知道正常的Java GC模式和Java堆空間使用情況。我正在使用JMeter測試我的Java 1.6應用程序。我正在收集JMX GC日誌並使用JMeter JMX GC和Memory插件擴展來繪製它們。 GC模式看起來非常穩定,大多數GC操作是30-40ms,偶爾是90ms。內存消耗呈鋸齒狀。 JHS用量不斷增加,例如到3GB,每40分鐘內存使用量就會自由下降到1GB左右。然而,最大 - 最小三角形增長,所以鋸齒高度不斷增長。它每40分鐘做一次完整的GC嗎?Java GC和Java堆空間使用的正常行爲是什麼?

回答

0

是的,最有可能的。不用猜測,你可以使用jstat來監測你的GC。

我建議你使用內存分析器來確保沒有什麼簡單的事情可以改善你正在生產的垃圾數量。

順便說一句,如果你增加年輕一代的規模,你可以減少垃圾進入終身空間的次數,從而減少整個收藏的頻率。如果您調整得足夠多,您可能會發現每天少於一次完整收藏。

對於一個更極端的情況下,我已經調整交易系統每天不到一個集(或大或小)

+0

我建議在VisualGC插件中使用'jvisualvm'。它清楚地說明了每個單獨的世代佔用情況,因此次要收藏和主要收藏之間的差異是顯而易見的。 –

+0

我們使用JMeter的GC插件,所以我們至少得到GC中的時間[ms]。 – user1340582

+0

@ user1340582這應該能夠告訴你GC是一個年輕的集合,一個老的集合還是一個完整的集合,因爲這可以通過JMX獲得。 –

0

Java的GC工作對象的世代而言。有年輕的,任期和經歷的世代。看起來就像你的情況一樣:每30-40ms GC只處理年輕一代(並將存活的對象轉移到終身職位)。每40分鐘它會執行全面收集(它會導致世界停止暫停)。注意:它不是按時間發生,而是按已用內存的百分比。

有幾個JVM選項,它允許您選擇代的尺寸,類型GC的(有幾種算法GC,在Java 1.6串行GC默認情況下使用,例如-XX:-UseConcMarkSweepGC) GC工作的參數。

你最好嘗試查找有關GC的世代,不同類型(算法是真的不同,他們中的一些允許以避免停了世界暫停在所有!)

+0

我跑了8小時的測試。在此期間,內存消耗進行了8次「深度潛水」。然而,4小時進入測試,它看起來像JBoss停止響應,因爲響應時間從500毫秒增加到大約40-50秒。然後服務器恢復正常。我想這是「停止世界」的停頓。然而,爲什麼它在4小時後做到了,而不是在那之後,超越了我。我會嘗試運行更長時間的測試。 – user1340582

+0

噢,我們有8GB的內存,並且使用JVM堆空間5GB,其中最小值和最大值是相等的。我們還使用「-XX:+ UseConcMarkSweepGC」選項 – user1340582

+0

您期望得到哪個結果?你想減少用於GC的時間嗎?無論如何,有幾種可能的方式:自定義jvm參數 - 更改內存大小,使用另一個GC;或者嘗試優化你的代碼(這是非常具體的解決方案)。 – arghtype

0

你的描述的大部分好文章一般來說,GC是如何工作的。但是,您的具體意見,尤其是數字,都不適用於一般情況。

首先,每個JVM都有一個或多個GC實現,您可以選擇使用哪一個。以最常用的一種,即SUN JVM(我喜歡這樣稱呼它)和通用服務器GC模式爲例。

首先,內存分爲4個區域。

  • 年輕一代擁有所有最近創建的對象。當這一代充滿時,GC通過停止你的程序工作,執行黑灰白算法,並獲取obselete對象並將它們刪除,從而實現「停止世界」的收集。所以這是你的30-40毫秒。

  • 如果一個物體在年輕的gen中存活了某一輪GC,它就會被轉移到swap一代。交換生成將對象保存到另一個GC - 然後將它們移動到舊一代。有2個交換世代,它有一個雙緩衝類型的東西來幫助年輕的gen加速工作。如果年輕的gen轉儲東西來交換gen並且發現swap gen大部分已經滿了,GC就會在swap gen上發生並且可能將存活的對象移動到舊的gen。這很可能會讓你的90毫秒,但我不是100%確定如何互換基因的作品。有人糾正我,如果我錯了。

  • 所有存活的對象都會被移到舊代。老一代只有在大部分時間纔會進行GC編輯。在你的情況下,每40分鐘。

  • 還有另一個「永久gen」用於加載你的jar目標字節碼和資源。

所有大小的區域都可以通過JVM參數進行調整。

你可以嘗試使用VisualVM,它會給你一個動態的想法。

P.S.並非所有的JVM/GC都以同樣的方式工作。如果您使用G1收集器或JRocket,可能會發生稍微不同,但總體思路是成立的。