java.lang.OutOfMemoryError即使很多

我正在尝试将2.5GB的txt文件读入我的应用程序。 我正在运行Win7 x64并且有43GB的内存可用(64GB)。 我尝试使用-Xmx -XX:MaxParmSize -XX:ParmSize等。这些都不会影响错误。 我还能尝试什么? 这个错误看起来很奇怪,因为我当然有足够的堆空间可用。

Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit at java.util.Arrays.copyOf(Unknown Source) at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source) at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source) at java.lang.AbstractStringBuilder.append(Unknown Source) at java.lang.StringBuilder.append(Unknown Source) at j.utilities.IO.loadString(IO.java:187) at j.utilities.IO.loadString(IO.java:169) at city.PreProcess.main(PreProcess.java:78) 

我在跑步

 java version "1.7.0_09" Java(TM) SE Runtime Environment (build 1.7.0_09-b05) Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode) 

非常感谢提前。

==============答案==============

好的,我刚用它测试过

 StringBuilder sb = new StringBuilder(); for ( int i=1; i<Integer.MAX_VALUE; i++ ) sb.append("x"); 

得到了

 Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit at java.util.Arrays.copyOf(Unknown Source) ... 

因此,它确实是StringBuilder,它试图构建一个大于Integer.MAX_VALUE的数组。

万一感兴趣

 StringBuilder sb = new StringBuilder(); int i=1; try { for ( ; i<Integer.MAX_VALUE; i++ ) sb.append("x"); } catch ( OutOfMemoryError e ) { System.out.println(i); // OUTPUT: 1207959551 System.out.println(Integer.MAX_VALUE); // OUTPUT: 2147483647 } 

使用StringBuilder,您可以累积1,207,959,550个字符 – 远小于Integer.MAX_VALUE。

你正试图分配一个太大的数组。 这是因为您正在尝试创建一个非常长的String。 由于数组是由整数索引的,因此数组不能超过Integer.MAX_VALUE元素。 即使您的堆大小非常大,您也无法分配具有多于Integer.MAX_VALUE元素的数组,因为您无法使用Integer索引其元素。 请参阅Java数组是否具有最大大小? 更多细节。

您可以创建一个具有大小的新StringBuilder,例如

  StringBuilder sb = new StringBuilder(Integer.MAX_VALUE); 

问题是你正在尝试读取一个比StringBuilder在其数组中更大的文件。 你有几个选择,例如:

1)你真的需要立刻将整个文件读入内存吗? 如果是这样,你必须将它读入几个StringBuilders。

2)按顺序处理文件。

3)将其读入压缩结构,并在需要时解压缩所需的部件。

您应该查看java命令的-Xmsn选项。

它指定内存分配池的初始大小。

编辑:我看到你已经做到了。

您可以在定义间隔中保存字符串缓冲区数据中的数据是List并清除StringBuffer