簡體   English   中英

為什么 JVM 需要這么長時間才能 GC 我無法訪問的 object?

[英]Why does it take the JVM so long to GC my unreachable object?

我一直在處理我們應用程序中的類加載器泄漏問題,最后到了所有對 CL 的引用都消失的地步。 在我的 memory 分析工具(使用 YourKit 和 jmap/jhat)中,我可以強制 GC 有時會立即擺脫我的類加載器,但其他時候(取決於應用程序的使用情況,但這是盡可能具體的)當我強制GC,CL 實例不會 go 離開。 我捕獲了一個 memory 快照並查看結果,它說這個 object 存在,但無法訪問。

這是古怪的部分......我只是偶然發現了這一點。

我可以強制執行我想要的全部 GC,但實例不會 go 離開。 但是,10-20 分鍾后,如果我再做一次完整的 GC,它確實會被收集。

(在此期間,應用程序大部分處於非活動狀態(並非完全處於活動狀態)。我的“延長”咖啡休息時間是導致這一發現的意外。)

所以我對這里泄漏的擔憂已經消失(希望如此),但現在的問題更多是試圖解釋這種行為。

任何人都知道什么可能導致 sun JVM 決定在 20 分鍾內不收集無法訪問的類加載器?

孫 JVM 版本詳情:

java version "1.6.0_23"
Java(TM) SE Runtime Environment (build 1.6.0_23-b05)
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b09, mixed mode)

我認為 Jeremy Heiler 走在正確的軌道上,這是一個最終確定的問題。 基本上,即使 GC 知道 object 無法訪問,在實際收集 object 之前可能仍然需要一段不確定的時間,因為它可能會排隊等待最終確定。 終結器線程將不得不完成 object(這可能需要一段時間,這取決於需要終結的其他對象數量以及它們的終結器的外觀),然后,在 object 完成之后,您需要另一個GC 重新發現 object 在實際收集之前無法訪問。

另外,對於 Sun JVM 上的 ClassLoader,它很可能直接分配到 PermGen。 因此,您不需要一個,而是兩個完整的 PermGen 掃描(一個將 object 放入最終隊列,然后第二個實際收集它)。 由於 PermGen 掃描很昂貴,我相信 Sun JVM 在默認設置下根本不會這樣做,即使有各種 GC 調整,它仍然非常不願意掃描 PermGen(特別是如果沒有很多其他 memory 壓力)。

如果不是使用System.gc()強制(嗯,我的意思是鼓勵)GC,如果您執行以下操作怎么辦:

System.gc();
System.runFinalization();
System.gc();

當然,即使這樣也不能保證有效,但它至少做了最少的必要工作來清理需要完成的大型 object。

一個可能的原因是類加載器被軟引用持有。 嘗試運行

-XX:SoftRefLRUPolicyMSPerMB=1

看看這是否有所作為。 這就是我的情況

可能是因為 JVM 使用分垃圾收集,但最終會進行完整的標記和清除

只是一個猜測:Classloader(及其加載的類)不在通常的堆中,而是在永久代(“PermGen”)中。 This part of the memory will be swiped much less often than everything else, since in normal conditions, class loaders don't go out of scope.

(可能有一些 GC 配置選項會影響這個頻率。)我想填充 PermGen 也會在那里觸發一個收集,但你通常不想這樣做。

事實上,為什么你需要收集你的類加載器?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM