2011-02-11 248 views
1

所以我有這個內存密集型的Java應用程序,它構建了一個有數百萬個節點的樹。利用方便的花花公子運行一些方法來獲取堆信息,我建,顯示當前內存的使用情況,如下圖所示一個可愛的小方法:Java垃圾收集問題

public void displayMemoryUsage() { 
    long maxMem = Runtime.getRuntime().maxMemory(); 
    long freeMem = Runtime.getRuntime().freeMemory(); 
    long heapMem = Runtime.getRuntime().totalMemory(); 
    long usedMem = heapMem - freeMem; 
    System.out.println("Memory used: " + (int) (usedMem * 100/maxMem) + "%"); 
} 

所以只是爲了測試一下,我已經在樹中展開根節點(2128個孩子),然後擴展每個孩子(樹中總共約400萬個節點)。內存顯示11%使用。然後,我將樹的根設置爲根的子項之一,並且這樣做可以刪除對根的其他子項的所有引用。從理論上講,這應該刪除原始根的孩子的2127/2128。我運行Java的Runtime.getRuntime()。gc()方法強制垃圾收集,並告訴它再次顯示內存使用情況。這一次,我得到了10%。從理論上講,這個新的百分比是不是應該在設定新根之前的0.05%,或者是價值的1/2128?

任何想法爲什麼它不正確拾取垃圾?

+6

對不起nitpicker ..但你不能_force_垃圾回收,你只是_suggest_ JVM這樣做。 http://download.oracle.com/javase/6/docs/api/java/lang/Runtime.html#gc%28%29 – Nishant 2011-02-11 06:02:44

回答

4

System.gc(和等效Runtime.gc)方法是一個建議到垃圾應收集的垃圾收集器,所以它不是一個真正的方法來「強制垃圾回收」:

從Java System.gc方法的API規範:

運行垃圾回收器。

調用gc方法表明, 的Java虛擬機的努力 朝 爲了使內存回收未使用的對象,他們 當前佔用快速 重用。 *當控制從 方法調用返回時,Java虛擬機 已盡最大努力從所有被丟棄的對象中收回 空間。

(着重號。)

此外,在一個技術性的一點點,即使垃圾收集確實發生,請記住,有一些存在於Java虛擬機上的其他對象除了你的程序,所以也會有一些內存開銷。

實際獲得有關樹的內存佔用量的一種方法是在創建樹之前和之後檢查內存使用情況 - 但請注意,即使此時可能會發生一些垃圾回收而你的樹正在建造,所以即使這不會是一個完美的指標。

這裏最好的選擇可能是使用一個探查器(例如JDK附帶的jvisualvm)來實際檢查堆的使用量。

0
  1. 您確定沒有對已刪除節點的任何引用?
  2. 你確定你在gc()之後等了很長時間,也就是說你多次建議它嗎?
1

您應該嘗試改爲調整您的應用程序!