java.lang.OutOfMemoryError 即使有很多

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13772802/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:55:23  来源:igfitidea点击:

java.lang.OutOfMemoryError even though plenty of

javaout-of-memory

提问by dotwin

I am trying to read a 2.5GB txt file into my application. I am running Win7 x64 and have 43GB of mem available (out of 64GB). I tried playing around with -Xmx -XX:MaxParmSize -XX:ParmSize etc. None of these affect the error. What else could I try? This error seems very odd as I certainly have enough heap space available.

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

I am running

我在跑步

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)

Thanks a lot in advance.

非常感谢。

============== ANSWER ==============

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

OK, I just tested it with

好的,我刚刚测试了它

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

and got

并得到

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

Thus, it really is StringBuilder which tries to build an array bigger than Integer.MAX_VALUE.

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

In case interested

如果有兴趣

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
}

With StringBuilder you can accumulate 1,207,959,550 chars - far less than Integer.MAX_VALUE.

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

回答by reprogrammer

You're trying to allocate an array that is too large. This is because you're trying to create a very long String. Since arrays are indexed by an integer, an array cannot have more than Integer.MAX_VALUEelements. Even if the your heap size is very large, you won't be able to allocate an array that has more than Integer.MAX_VALUEelements, simply because you cannot index its elements using an Integer. See Do Java arrays have a maximum size?for more details.

您正在尝试分配一个太大的数组。这是因为您正在尝试创建一个很长的字符串。由于数组由整数索引,因此数组不能有多个Integer.MAX_VALUE元素。即使您的堆大小非常大,您也无法分配包含多个Integer.MAX_VALUE元素的数组,因为您无法使用Integer. 请参阅Java 数组有最大大小吗?更多细节。

回答by Diego Basch

You could create a new StringBuilder with a size, e.g.

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

    StringBuilder sb = new StringBuilder(Integer.MAX_VALUE);

The problem is that you're trying to read a file that's larger than what StringBuilder can have in its array. You have several options, e.g.:

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

1) Do you really need to read the entire file into memory at once? If so, you'll have to read it into several StringBuilders.

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

2) Process the file sequentially.

2) 依次处理文件。

3) Read it into a compressed structure, and uncompress the parts you need when you need them.

3)读成压缩结构,需要的时候解压需要的部分。

回答by Raj

You can hold the data in string buffer data is List<String>in define interval and clear the StringBuffer.

您可以将字符串缓冲区中的数据保存List<String>在定义间隔内并清除StringBuffer.

回答by Bryan Glazer

You should look into the -Xmsn option for the java command.

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

It specifies the initial size of the memory allocation pool.

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

Edit: I see you've already done that.

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