2012-07-08 154 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