【问题标题】:java.lang.OutOfMemoryError even though plenty ofjava.lang.OutOfMemoryError 即使有很多
【发布时间】:2012-11-26 04:54:58
【问题描述】:

我正在尝试将 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。

【问题讨论】:

  • 看起来您正在尝试分配一个数组。数组有多少个元素?
  • PreProcess.java:78的代码是什么?
  • j.utilities.IO 是什么?如果是你的代码粘贴IO.java:169.
  • StringBuilder 内部是否使用数组?
  • IO.loadString(IO.java:187) 是 "sb.append(line);"

标签: java out-of-memory


【解决方案1】:

您正在尝试分配一个太大的数组。这是因为您正在尝试创建一个非常长的字符串。由于数组由整数索引,因此数组不能有超过Integer.MAX_VALUE 个元素。即使您的堆大小非常大,您也无法分配具有超过Integer.MAX_VALUE 元素的数组,因为您无法使用Integer 对其元素进行索引。详情请见Do Java arrays have a maximum size?

【讨论】:

  • StringBuilder 内部是否使用数组?或者可能是一个字符串被解释为一个字符数组?
  • 它应该有一个char[]
  • 是 StringBuffer/StringBuilder 确实将其数据存储在一个数组中。但是如果你有一个大于 2GB 的字符串,那么你做错了。\
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

        StringBuilder sb = new StringBuilder(Integer.MAX_VALUE);
    

    问题是您正在尝试读取的文件比 StringBuilder 数组中的文件大。您有多种选择,例如:

    1) 你真的需要一次将整个文件读入内存吗?如果是这样,您必须将其读入多个 StringBuilders。

    2) 按顺序处理文件。

    3) 将其读入压缩结构,在需要的时候解压需要的部分。

    【讨论】:

      【解决方案4】:

      您可以在定义的区间内保存字符串缓冲区数据为List&lt;String&gt;的数据并清除StringBuffer

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-04
        • 2013-01-13
        • 2013-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多