2013-10-14 43 views
2

我的應用程序出現問題,並且縮小了一點。我的記憶似乎有未使用的物體。然而,當我在Netbeans IDE的Profiler中按下「收集垃圾」時,GC並沒有收集它們(即使程序本質上沒有空閒,即使沒有處理線程處於活動狀態也不會收集它們) 。Java GC未收集某個對象

我發現負責臨時使用的存儲器的高量的代碼:

private Integer getWhiteLines(BufferedImage image) { 
    Map<Integer, List<Color>> heightColors = new HashMap<>(); 

    for (int h = 0; h < image.getHeight(); h++) { 
     List<Color> colors = new ArrayList<>(); 
     for (int w = 0; w < image.getWidth(); w++) { 
      int colorRGBA = image.getRGB(w, h); 
      Color color = new Color(colorRGBA, true); 
      colors.add(color); 
     } 
     heightColors.put(h, colors); 
    } 

    Integer whiteLines = 0; 
    for (Map.Entry<Integer, List<Color>> entry : heightColors.entrySet()) { 
     Color avgColor = avgColor(entry.getValue()); 
     if (isWhite(avgColor)) { 
      whiteLines++; 
     } 
    } 
    return whiteLines; 
} 

它列出的每個像素的圖像中的顏色(以前一個PDF文件)。

這個問題也很大,例如在某些PDF上,Color對象佔用了14MB的內存。

爲什麼會發生這種行爲,我將如何解決它?

+0

avgColor做什麼? – arynaq

+0

@arynaq通過從列表中返回一個「顏色」來給出所有顏色的平均值。 – skiwi

+0

簡單的治療方法是避免首先存儲所有顏色。當你只需要平均值時,就可以實時計算它。 – Henry

回答

0

當應用程序處於空閒狀態時,您無法說出何時收集垃圾內存。你有沒有遇到過內存異常?另外,如果應用程序佔用大量內存,則可以使用-Xms -Xmx JVM參數來限制它。

對於此類型的任務,您應該考慮在迭代輸入值時動態計算值。

如果您不能在飛行中執行操作,則應考慮重新使用第一次創建的對象。

1

只有當您需要內存分配並且您的虛擬機沒有足夠資源時,GC纔會強制收集內存。您可以減少佔地面積這樣:

private Integer getWhiteLines(BufferedImage image) { 
    Integer whiteLines = 0; 
    for (int h = 0; h < image.getHeight(); h++) { 
     List<Color> colors = new ArrayList<>(); 
     for (int w = 0; w < image.getWidth(); w++) { 
      int colorRGBA = image.getRGB(w, h); 
      Color color = new Color(colorRGBA, true); 
      colors.add(color); 
     } 

     Color avgColor = avgColor(colors); 
     if (isWhite(avgColor)) { 
      whiteLines++; 
     } 
    } 

    return whiteLines; 
} 
1

有你要保存colors ArrayList中的每一行成地圖,然後遍歷該單獨計算平均顏色,並確定它是否是一種白色無明顯原因還是不行。你可以做所有的在單個循環:

private Integer getWhiteLines(BufferedImage image) { 
    Integer whiteLines = 0; 
    for (int h = 0; h < image.getHeight(); h++) { 
     List<Color> colors = new ArrayList<>(); 
     for (int w = 0; w < image.getWidth(); w++) { 
      int colorRGBA = image.getRGB(w, h); 
      Color color = new Color(colorRGBA, true); 
      colors.add(color); 
     } 
     Color avgColor = avgColor(colors); 
     if (isWhite(avgColor)) { 
      whiteLines++; 
     } 
    } 
    return whiteLines; 
} 

,這將導致在走出去的範圍更早的對象(因爲Color對象只保存外循環的每個迭代,而不是整個該函數的執行時間)以及該內存可用於早期的垃圾回收。

但值得注意的是,垃圾收集器不一定會在程序閒置的時候運行。這不是一個免費的過程,因爲這種垃圾收集只有在實際需要釋放內存時纔會發生。有資格進行垃圾回收的對象並不意味着它的內存將立即回收。

+0

有趣。我們寫了相同的代碼,以擊鍵... –

+0

@LaurentLARIZZA並不令人驚訝;只有一種邏輯方法可以繞過他們已經擁有的代碼的必要部分,並且我不希望在沒有必要時使用空格。 –