2016-02-25 59 views
6

我有,我将使用一个非常大的short[]阵列方案更大的堆空间:Java要求比什么是合理的

import java.lang.Math; 

public class HPTest { 

    public static void main(String[] args) { 
     int n = 30; 
     short[] a = new short[(int)Math.pow(2,n)]; 
    } 
} 

据我所知,short[]阵列应每元素中使用2个字节,因此具有2^30元素的数组应该需要大约2吉比的RAM。

为了运行程序,因此,我试图

java -Xms2000m HPTest 

,但仍然得到了堆空间错误。即使在3000m我也得到了同样的错误,但在4000m它工作。

任何想法,为什么我必须远远高于2000m的估计限制?

编辑: 正如许多用户指出的那样,我在声明short需要1个字节而不是2个字节时犯了一个非常尴尬的错误。那么问题应该是为什么它不能满足2000m

+7

短是2个字节... –

+1

一个'byte'是一个字节,因此名字。顺便说一句'1 << n'是计算2的幂的更有效的方法。 –

+0

即使如此,3000m/3gb应该足够他吗? –

回答

5

这么大的东西,在堆外面会更加快乐。你最好查找NIO并使用直接字节缓冲区来备份大型短阵列。这个内存可以放在堆外,远离垃圾收集器(可能有时候感觉倾向于将缓冲区从一个区域复制到另一个区域)。

请参阅java.nio.ShortBuffer并开始从那里挖掘。

+0

谢谢!第二个想法,我可能能够切换到一个字节数组。无论如何,我将基本上使用数组作为与0到2^30-1的所有整数的不同容器对应的标志数组。因此,当我遍历这些整数时,我将把我的短/字节数组的相应索引处的标志设置为某个值。就我所见,我可以通过每次在缓冲区调用put()来完成此操作。这会很慢吗? –

+0

实际上,这个大的分配直接进入“老一代”池,并且不会被垃圾收集器复制。我只是凭经验测试这是真实的,我似乎记得在某个地方阅读,但我目前没有参考。 – Andreas

+0

@AlexandreVandermonde如果他们只是标志,你应该把它设置为一个布尔数组,并且JVM可以将8个布尔变成一个字节。 – Andreas