2009-07-23 91 views
11

我們已經開啓詳細GC日誌來跟蹤已知內存泄漏,並得到了以下項在日誌中:「GC--」在java垃圾收集日誌中的含義是什麼?

... 
3607872.687: [GC 471630K->390767K(462208K), 0.0325540 secs] 
3607873.213: [GC-- 458095K->462181K(462208K), 0.2757790 secs] 
3607873.488: [Full GC 462181K->382186K(462208K), 1.5346420 secs] 
... 

據我所知,第一和第三的,但什麼是「GC- 「一個意思?

+2

鑑於時間戳和存儲量我猜想它進行垃圾回收,但失去的可用內存(因爲其他對象是在並行創建) – Yishai 2009-07-23 23:25:37

+0

伊沙伊,謝謝,使有很大的意義。不知道它是否正確,但很可能。 – RodeoClown 2009-07-23 23:43:20

+0

想把它放在一個答案,所以我可以投它/接受它? :) – RodeoClown 2009-07-23 23:46:09

回答

12

我在GC輸出得到了這幾樣行:

44871.602: [GC-- [PSYoungGen: 342848K->342848K(345600K)] 961401K->1041877K(1044672K), 0.1018780 secs] [Times: user=0.16 sys=0.00, real=0.11 secs] 

我讀伊沙伊的答案,它會是有意義的,但我想看看它爲自己在Java GC的源代碼,當JVM在GC日誌中打印「 - 」以及爲什麼。

因爲據我所知,年輕一代的「並行清除」是一個世界末日的GC,所以不可能是與該GC並行創建的任何對象。 (見https://blogs.oracle.com/jonthecollector/entry/our_collectors

您可以在JDK源代碼中找到這個(見http://hg.openjdk.java.net/jdk7/jdk7) g1CollectedHeap.cpp和psScavenge.cpp

jdk7-ee67ee3bd597/hotspot/src/share$ egrep -h -A2 -B5 -r '"\-\-"' * 
# G1 Collector 
if (evacuation_failed()) { 
    remove_self_forwarding_pointers(); 
    if (PrintGCDetails) { 
    gclog_or_tty->print(" (to-space overflow)"); 
    } else if (PrintGC) { 
    gclog_or_tty->print("--"); 
    } 
} 
-- 
# Parallel Scavenge Collector 
promotion_failure_occurred = promotion_failed(); 
if (promotion_failure_occurred) { 
    clean_up_failed_promotion(); 
    if (PrintGC) { 
    gclog_or_tty->print("--"); 
    } 
} 

原因GC--與並行清除收集

Young GC遇到促銷失敗(參見http://mail.openjdk.java.net/pipermail/hotspot-gc-use/2010-March/000567.html):

促銷失敗是一種不成功的清理行爲,因爲舊生活中沒有足夠的空間來做所有必要的促銷活動。清除 實質上是展開的,然後完成整個堆的完整STW壓縮。

「沒有足夠的空間」並不一定意味着沒有老足夠的空間,但是,舊的空間是大量碎片(見http://blog.ragozin.info/2011/10/java-cg-hotspots-cms-and-heap.html):

[ ...]無法找到一定數量的連續內存來促進特定的大對象,即使總空閒字節數足夠大。

這兩個JVM選項可以幫助您分析堆碎片(見http://blog.ragozin.info/2011/10/java-cg-hotspots-cms-and-heap.html):

-XX:+PrintPromotionFailure 
-XX:PrintFLSStatistics=1 

原因GC--與G1收集

與G1中的疏散失敗當一個倖存者地區沒有足夠的空間來存放一個年輕地區的倖存對象時。

我不知道G1收集器是否對Full GC的疏散失敗做出響應。

1

我從here如下:

前兩行表示自己也有 兩個小集合和一個主要 之一。 箭頭前後的數字分別表示垃圾 收集前後 活物的組合大小。輕微 集合後,計數包括對象 這不一定是活着,但 無法回收,或者是因爲他們 直接活着,或者是因爲他們 內或從 年老代引用。在 括號S中的總可用空間 的數量,不計算在 永久代的空間,這是 總堆減去一個 在第三行的主要收集 是相似的格式。標記 -XX:+ PrintGCDetails打印有關集合的其他信息。 附加信息 此標誌可能會隨虛擬機的每個版本的 更改。 帶有 -XX:+ PrintGCDetails標誌的附加輸出特別隨着Java虛擬 機器的 開發需求而變化。的倖存者空間。次要收集大約需要 秒。

0

Yishai在評論中說:

鑑於時間戳和存儲量我猜想它進行垃圾回收,但失去的可用內存(因爲其他對象是在並行創建)

1

事實上,在我們自己的日誌中遇到這個問題後,我和一個同事就有了另一種解釋,似乎更符合事實。

你會注意到在這個例子中,一個完整的GC遵循這個奇怪的次要GC行。我可以證實,當我們的原木出現時,情況總是如此。你也可以看到年輕人的開始和結束的大小是平等的,我可以再次確認這一點。

我們相信這裏發生的事情是虛擬機已經啓動了一個小型GC,並且在無法釋放任何東西或花費太長時間而無法釋放任何東西之後,決定改爲使用Full。