java - 尽管有足够的可用内存,但巨大的数组仍会耗尽内存

标签 java arrays memory

使用 -Xmx1G 标志来提供 1 GB 的堆,以下内容按预期工作:

public class Biggy {
    public static void main(String[] args) {
        int[] array = new int[150 * 1000 * 1000];
    }
}

数组应该代表大约 600 MB。

但是,以下会抛出 OutOfMemoryError:

public class Biggy {
    public static void main(String[] args) {
        int[] array = new int[200 * 1000 * 1000];
    }
}

尽管数组应该表示大约 800 MB,因此很容易放入内存中。

丢失的内存去哪儿了?

最佳答案

在 Java 中,堆中通常有多个区域(和子区域)。你有一个年轻而老牌的地区, Collection 家最多。大型数组会立即添加到永久区域,但是根据您的最大内存大小,将为年轻空间保留一些空间。如果您缓慢地分配内存,这些区域会调整大小,但是像这样的大块可能会像您所见的那样简单地失败。

鉴于内存通常相对便宜(并非总是如此),我只会将最大值增加到您希望应用程序在使用那么多时失败的程度。

顺便说一句:如果您有这样的大型结构,您可能会考虑使用直接内存。

IntBuffer array = ByteBuffer.allocateDirect(200*1000*1000*4)
                            .order(ByteOrder.nativeOrder()).asIntBuffer();

int a = array.get(n);
array.put(n, a+1);

写起来有点乏味,但有一个很大的优势,它几乎不使用堆。 (超过 1 KB)

关于java - 尽管有足够的可用内存,但巨大的数组仍会耗尽内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7298455/

相关文章:

java - 有编辑程序流程的库吗?

java - Eclipse Project Explorer 中的拖放以某种方式对 Java 实体禁用

java - C++语言内存模型

java - 将动态变量发送为 ftl 格式

java - 如何使用调制解调器或网关从 java Web 应用程序发送短信?

c# - 不同泛型的数组

Java类与数组内存大小?

音频缓冲区上的 java.lang.OutOfMemoryError

php - 通过 ArrayAccess 访问多维数组

C:将矩形切割成正方形的算法