2016-11-28 225 views
0

我对BlueJ的Java堆空间有问题。 我已经写了一个程序,它读入一个字符串的.txt文件并遍历字符串的所有字符并做一些事情(猜测这并不重要)。一些.txt文件非常大(约2亿个)。 如果我尝试用这些.txt执行程序,我得到这个“异常在线程”AWT-EventQueue-0“java.lang.OutOfMemoryError:Java堆空间”错误代码。我将bluej.def中的bluej.windows.vm.args和bluej.windows.vm.args增加到8gb。它仍然不起作用。但我实际上猜测即使是一个2亿字符的字符串也不会超过这个限制。 这是我的我在.TXTBlueJ的Java堆空间

try 
    { 
     FileReader reader = new FileReader(input.getText()); 
     BufferedReader bReader = new BufferedReader(reader); 
     String parcour = ""; 
     String line = bReader.readLine(); 
     while(line != null) 
     { 
      parcour += line; 
      line = bReader.readLine();    
     } 

input.getText()获取文件路径如何阅读代码。 我会很感激的答案。谢谢:) - Cyaena

+1

您正在将整个文件存储在'parcour'变量中。这会吃掉很多的记忆。另外,在将数据附加到字符串 – ar34z

+0

时考虑使用'StringBuilder',但实际上String不应该占用那么多的内存,不是吗?我必须使用StringBuilder有什么优势?我该如何粗略设置它? – Cyaena

+1

我不是解释内存使用情况的正确人选,但存储了200万个。内存中的字符听起来不太有希望。在循环中连接字符串时,“StringBuilder”更快。你想用这2亿行做什么?也许这可以帮助你:http://stackoverflow.com/questions/10202905/is-it-advisable-to-store-large-strings-in-memory-or-repeatedly-read-a-file有关内存使用情况的更多信息:http://www.javamex.com/tutorials/memory/string_memory_usage.shtml – ar34z

回答

0

在下面的说明中,只有数据的纯内存在范围内。所有额外的内存需求的结构被遗漏。这是更详细的概述。

存储器被在那些线

String parcour = ""; 
... 
String line = bReader.readLine(); 
... 
parcour += line; 

线parcour += line吃掉编译成类文件作为

new StringBuilder().append(parcour).append(line).toString() 

假设parcour包含大小为10 MB的字符串和line将大小的2 MB。然后在parcour += line;分配的内存将是(大约)需要

// creates a StringBuilder object of size 12 MB 
new StringBuilder().append(parcour).append(line) 

// the `.toString()` would generate a String object of size 12 MB 
new StringBuilder().append(parcour).append(line).toString() 

你的代码之前,新创建的字符串被分配到parcour约34 MB。

parcour       = 10 MB 
the temporary StringBuilder object = 12 MB 
the String fromStringBuilder  = 12 MB 
------------------------------------------ 
total        34 MB 

一个小的演示片段,表明OutOfMemoryException比目前预期的要早得多。

OOMString.java

class OOMString { 
    public static void main(String[] args) throws Exception { 
     String parcour = ""; 
     char[] chars = new char[1_000]; 
     String line = new String(chars); 
     while(line != null) 
     { 
      System.out.println("length = " + parcour.length()); 
      parcour += line; 
     }   
    } 
} 

OOMStringBuilder.java

class OOMStringBuilder { 
    public static void main(String[] args) throws Exception { 
     StringBuilder parcour = new StringBuilder(); 
     char[] chars = new char[1_000]; 
     String line = new String(chars); 
     while(line != null) 
     { 
      System.out.println("length = " + parcour.length()); 
      parcour.append(line); 
     }   
    } 
} 

两个片段做同样的。他们在parcour中添加了1000个charcater字符串,直到OutOfMemoryException被引发。为了加快速度,我们将堆大小限制为10 MB。

的输出java -Xmx10m OOMStringBuilder

length = 2052000 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 

java -Xmx10m OOMString

length = 1048000 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 

输出当你执行的代码,你会发现,OOMString需要更多的时间来失效(甚至在更短的长度)比OOMStringBuilder

您还需要记住单个字符是两个字节长。如果您的文件包含100个ASCII字符,则它们在内存中占用200个字节。

也许这个小小的演示可以为你解释一点点。

0

我也有BlueJ和堆空间错误以及一些问题。就我而言,打开终端会使整个应用程序崩溃。我怀疑这与生成大量输出有关,与您的大型字符串类似。就我而言,我意外地创造了一个无处不在的循环,打破了终端窗口。我不得不删除所有的属性文件。现在BlueJ再次工作,不再发生OutOfMemoryErrors。 我希望这可能对其他情况也有帮助。