在 Java 中加入字符串列表时出现 OutOfMemoryError

OutOfMemoryError when joining a list of Strings in Java

所以。我试过:

StringBuilder sb = new StringBuilder();
for(String bufferItem: buffer){
    sb.append(bufferItem);
}

我也试过了:

String.join("\n", buffer)

我要在超过 100GB 的系统的内存中加入一个大文件(10GB 以下)。以下是堆栈跟踪。我该如何解决这个问题?

Exception in thread "main" java.lang.OutOfMemoryError
    at java.lang.AbstractStringBuilder.hugeCapacity(AbstractStringBuilder.java:161)
    at java.lang.AbstractStringBuilder.newCapacity(AbstractStringBuilder.java:155)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:125)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
    at java.lang.StringBuilder.append(StringBuilder.java:136)
    at java.lang.StringBuilder.append(StringBuilder.java:76)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:484)
    at java.lang.StringBuilder.append(StringBuilder.java:166)
    at java.util.StringJoiner.add(StringJoiner.java:185)
    at java.lang.String.join(String.java:2504)

首先,可能不建议使用那么大的内存,我会把它分成大小合理的块(也许一次加入 100 个字符串,然后写入一个文件)。如果你真的必须使用那么多内存,那么你需要将 -Xmx10G 传递给 JVM。这会分配更多堆 space 供 Java 使用。

您不能创建包含那么多字符的字符串。 OutOfMemoryError 不是因为堆已满,而是因为您正在尝试构建一个大于最大可能大小的字符串。

最大可能大小定义为 2 的 31 次方减 1 减 8。如果您在文件中仅使用单字节字符,则大约为 2Gb。查看 AbstractStringBuilder.

的来源
/**
 * The maximum size of array to allocate (unless necessary).
 * Some VMs reserve some header words in an array.
 * Attempts to allocate larger arrays may result in
 * OutOfMemoryError: Requested array size exceeds VM limit
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

您根本无法创建比这更大的字符串。

当您可以在将文件流式传输到磁盘时加入它们,为什么要加入内存中的文件?