2013-01-20 48 views
0

我正在用java编写一个程序,它必须利用一个大的散列表,散列表可以越大越好(这是一个国际象棋程序:P)。基本上,作为我的散列表的一部分,我有一个“long []”数组,“short []”数组和两个“byte []”数组。所有这些都应该是相同的大小。但是,当我将表格大小设置为一千万时,它崩溃并显示“java堆内存不足”。这对我来说没有意义。以下是我的看法:在Java中使用太多的Ram

1 Long + 1 Short + 2 Bytes = 12 bytes 
x 10,000,000 = 120,000,000 bytes 
/1024 = 117187.5 kB 
/1024 = 114.4 Mb 

现在,114 Mb的RAM对我来说似乎不是太多。总的来说,我的CPU在我的Mac上拥有4Gb的RAM,并且我有一个名为FreeMemory的应用程序,它显示了我有多少内存可用,运行该程序时它的容量是2Gb左右。另外,我设置了像-Xmx1024m这样的java选项,所以java应该可以使用多达一个内存。那为什么它不让我分配114Mb?

+2

您可以使用内存分析器查看究竟发生了什么。 – NPE

+0

你可以尝试较小的尺寸?排除它可能是一些很棒的递归。 –

+2

你能想出一个你认为占用太多空间的最小自包含的例子,并将它与你正在使用的确切'java'命令行一起发布吗? – NPE

回答

0

一直没有考虑到每个对象是一个参考,还可以使用内存,更多“隐藏的东西” ......我们还必须考虑到也对齐......字节并不总是一个字节;-)

,看看有多少内存真的在使用中,你可以使用一个分析器:如果您使用的是标准的HashMap(或JDK类似)

,每个“长“(拳击/拆箱)真的超过8bytes),你可以使用这个作为基地...(使用更少的内存)

0

从我所读到的关于BlueJ以及严重的技术信息几乎是不可能发现的,BlueJ VM很可能根本不支持原始类型;你的数组实际上是装箱的基元。 BlueJ使用所有Java功能的子集,重点在于面向对象。

如果是这样的话,再加上考虑到BlueJ虚拟机的优先级列表中的性能和效率相当低,您可能实际上使用的存储容量比您想象的要多得多:整个数量级是相当可想象的。

1

你预测它应该使用114 MB,如果我运行这个(在Windows中有4 GB)

public static void main(String... args) { 
    long used1 = memoryUsed(); 
    int Hash_TABLE_SIZE = 10000000; 
    long[] pos = new long[Hash_TABLE_SIZE]; 
    short[] vals = new short[Hash_TABLE_SIZE]; 
    byte[] depths = new byte[Hash_TABLE_SIZE]; 
    byte[] flags = new byte[Hash_TABLE_SIZE]; 
    long used2 = memoryUsed() - used1; 
    System.out.printf("%,d MB used%n", used2/1024/1024); 
} 

private static long memoryUsed() { 
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
} 

打印

114 MB used 

我怀疑你是在做别的事情是你的问题的原因。

我正在使用Oracle HotSpot Java 7更新10

+0

......就像使用BlueJ而不是真正的JVM一样。 –

+0

@MattBall我不认为我需要提供使用的JVM,但我怀疑你是对的。 –

+0

上半个小时我一直忙于研究BlueJ,它的功能集似乎指向构建在JVM之上的JVM。 BlueJ是用Java编写的,但提供了许多类似动态语言的交互功能,并且无法在使用生产虚拟机的专业IDE中进行复制。 –