2012-07-08 155 views
0

我使用的是Swing,我有一個包含幾個JPanel的JFrame,其中一個JTextArea。JTextArea.setText(null);不釋放內存

當用戶點擊某個菜單時,設置JTextArea內容(ActionListener.actionPerformed(populate()))。

的內容是從30MB文本文件採取:

private void populate() { 
     StringBuilder strB = new StringBuilder(); 
     try { 
      FileReader fr = new FileReader("file30mb.txt"); 
      BufferedReader br = new BufferedReader(fr); 
      String strLine; 

      while ((strLine = br.readLine()) != null) { 
       strB.append(strLine).append(System.getProperty("line.separator")); 
      } 

      fr.close(); 
      br.close(); 
     } catch (IOException e) { 
      System.err.println(e); 
     } 

     jTextArea1.setEditable(false); 
     jTextArea1.setText(strB.toString()); 
     jTextArea1.setCaretPosition(0); 
} 

這個過程需要大量的內存使用情況,約200MB。

還有另一個菜單,當用戶點擊它時,JTextArea被清除(基本上它調用了一個方法,它不會執行jTextArea1.setText(null))。該事件的處理方式與之前相同:ActionListener.actionPerformed(免費())

因此,當JTextArea爲空時,我認爲內存使用率比以前低......但不幸的是這不是真的。如果我進入任務管理器,我會看到之前的內存使用情況(大約200MB),但JTextArea是空的!

我錯過了什麼?

編輯我也試過這樣:

jTextArea1.setText(strB.toString()); 
jTextArea1.setText(""); 
Runtime r = Runtime.getRuntime(); 
r.gc(); 
System.out.println(jTextArea1.getDocument().getLength()); // prints "0" 

但它仍然需要內存200MB。

編輯2如果我刪除了「GUI部分」(我的意思是jTextArea1.setText()等),它仍然需要大量的內存。它應該佔用「0內存」,因爲我沒有在JTextArea中寫任何東西,但我只是讀了一個文本文件,然後什麼都不做。我錯了嗎?

+2

GC可能不會立即採取行動。你是否在任何地方保留對大字符串的其他引用? – Tudor 2012-07-08 17:16:52

+0

請測試JTextArea.getDocument(JTextComponent的模型),然後確定其getLength() – mKorbel 2012-07-08 17:18:54

+0

我沒有任何其他引用大字符串任何地方......他們只在該函數。我會測試你的建議。 – HBv6 2012-07-08 17:33:55

回答

3

幾個原因:

  • 垃圾回收週期性地運行,也不會釋放內存立即

  • JVM進程的內存和堆內存使用量是兩個不同的東西。啓用詳細的GC日誌記錄或使用jconsole/jvisualvm連接到您的應用程序並檢查真正的堆使用情況。運行GC手動

  • 按Ctrl +ž仍然工作,讓您恢復以前的(30 MB)內容是什麼?你的想法...

如果這些都不是正確的,使用內存分析器像Eclipse MAT找出擁有這個龐大對象的引用(你會發現char[] 60 MB的大小)。

+0

Ctrl + Z不起作用。所以我試圖手動運行GC,但它仍然需要200MB的內存(我編輯了我的第一篇文章) – HBv6 2012-07-08 17:42:33

+0

好的建議+1 – mKorbel 2012-07-08 18:02:09

+0

@PierpaoloBagnasco:那麼,是什麼問題? – 2012-07-09 16:13:45