Java内存2D阵列(Java Out of memory 2D Array)

2019-08-16 16:31发布

我想下面创建一个二维数组。

int NUM_RECORDS = 100480507;

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

它不应该是足有100480507 * 6 ~= 0.6 GB

这个问题为好。

但这种阵列的创作耗尽内存。 我已经通过JVM ARGS分配4G到我的java程序。

这怎么解释呢? 我是我错过了一些琐碎的事情在这里?

这是我的计划

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");
   }
}

Answer 1:

每个阵列具有一个开销(例如,参照IBM文档上它们的开销- > http://www.ibm.com/developerworks/java/library/j-codetoheap/index.html )。 在你的情况,你正在创建它们的100480507!

如果你改变你的代码为“ 字节[] completeArray =新的字节[NUM_RECORDS * 6]”,根据你的理论,它应该要求相同的空间! 但是,我相当肯定这将作为有至少开销。 您也可以尝试“的byte [] [] completeArray =新的字节[6] [NUM_RECORDS]。” 这应该工作太(小的开销)。

我知道这不会解决您的问题 - 但我希望这会给你的开销一些观点。



Answer 2:

我检查和谐JVM中的对象布局(JVM的其它实施方式是类似我想)。 在Java中每个对象都有包含JVM的重要信息的对象标题。 最重要的是该对象的类( 一个字 )的参考。 此外,也有使用由GC和管理同步,即,锁定字(因为每个对象可以被同步),其占用了另一个字 (使用部分单词将是坏的性能)的一些标志。 所以这是2个字,其是在32位的系统的8个字节,并且在64位的16个字节。 阵列还需要一个int字段为阵列的长度,这是另一种的4个字节 ,在64个的系统可能的8个字节 。 因此,对于每个阵列,我们有32位机12个附加字节,并且可以是64位机器上24个字节。

在你的程序中,你有数组的数组6。 100480507 1D阵列。 因此,附加的存储器消耗量约为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长更改元素类型:

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%。



文章来源: Java Out of memory 2D Array