Java 内存不足二维数组

问题描述 投票:0回答:3

我正在尝试创建一个二维数组,如下所示。

int NUM_RECORDS = 100480507;

byte[][] completeArray = new byte[NUM_RECORDS][6];

拥有这还不够吗

100480507 * 6 ~= 0.6 GB

另请参阅这个问题。

但是创建这个数组会耗尽内存。我已经通过 JVM args 为我的 java 进程分配了 4G。

这该如何解释呢?我在这里错过了一些微不足道的事情吗?

这是我的程序

public class MemTest {

   public static void main(String[] args) {
       int NUM_RECORDS = 100480507;
       byte[][] completeArray = new byte[NUM_RECORDS][6];
       System.out.println("Array created");
   }
}
java memory-management arrays out-of-memory
3个回答
2
投票

每个数组都有开销(例如,请参阅有关其开销的 IBM 文档 -> http://www.ibm.com/developerworks/java/library/j-codetoheap/index.html)。在你的例子中,你正在创建 100480507 个!

如果您将代码更改为“byte[]completeArray = new byte[NUM_RECORDS*6];”,根据您的理论,它应该需要相同的空间!但是,我相当确定这会起作用,因为开销最少。您也可以尝试“byte[][]completeArray = new byte[6][NUM_RECORDS];”这也应该有效(开销较小)。

我知道这不会解决您的问题 - 但我希望这能让您对开销有一些看法。


1
投票

我检查了 Harmony JVM 中的对象布局(我想 JVM 的其他实现也类似)。 java中的每个对象都有一个对象头,其中包含JVM的重要信息。最重要的是对对象类的引用(一个词)。此外,GC 使用一些标志来管理同步,即锁字(因为每个对象都可以同步),它占用另一个“一个字”(使用部分字会降低性能)。所以这是 2 个字,在 32 位系统上是 8 个字节,在 64 位系统上是 16 个字节。数组还需要一个 int 字段来表示数组长度,这在 64 位系统上又是 4 字节,可能是 8 字节。因此,对于每个数组,在 32 位机器上我们有 12 个额外字节,在 64 位机器上可能有 24 个字节。 在你的程序中,你有 6 个数组。 100480507 一维数组。所以额外的内存消耗大约是1.2 + 0.6 GB,这是一个非常大的连续内存块。开销约为200%。

当我们将代码更改为:

public class MemTest { public static void main(String[] args) { int NUM_RECORDS = 100480507; byte[] completeArray = new byte[NUM_RECORDS * 6]; System.out.println("Array created"); } }

我们只创建1个数组,因此开销非常小。总共约0.6GB。 

当代码更改为:

public class MemTest { public static void main(String[] args) { int NUM_RECORDS = 100480507; byte[][] completeArray = new byte[NUM_RECORDS][6]; System.out.println("Array created"); } }

我们总共有 7 个数组。该计划将立即结束。 

在您的代码风格中创建另一个 0.6GB 内存,但将元素类型从 int 更改为 long:

public class MemTest { public static void main(String[] args) { int NUM_RECORDS = 12560063; long[][] completeArray = new long[NUM_RECORDS][6]; System.out.println("Array created"); } }

程序也可以立即结束。开销约为150M/600M = 25%。


0
投票

byte[][] 它是字节数组对象的数组(在您的情况下为 100480507 个对象 *(12 字节 + 6 字节数据 - 在 32 位系统中,在 64 位系统中更多)

100480507 * (12 + 6) = 1,8 GB

100480507 * (20 + 6) = 2,6 GB

示例 byte[][] 对象 = new byte[6][6]:

在此输入图片描述

© www.soinside.com 2019 - 2024. All rights reserved.