我有以下测试程序:
public static void main(String[] args)
{
HashMap<Integer, String> hm = new HashMap<Integer,String>();
int i = 1;
while(true)
{
hm.put(i, "blah");
i++;
System.out.println("############");
System.out.println("Max mem: " + Runtime.getRuntime().maxMemory());
System.out.println("Total mem: " + Runtime.getRuntime().totalMemory());
System.out.println("Free mem:" + Runtime.getRuntime().freeMemory());
}
}
如果我运行此程序,我会得到以下输出:
...
############
Max mem: 8060928
Total mem: 8060928
Free mem:334400
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.addEntry(Unknown Source)
at java.util.HashMap.put(Unknown Source)
at Test.main(Test.java:14)
为什么我得到“OutOfMemoryError”异常虽然freeMemory()方法返回有更多的空闲内存???如果有办法使用所有freeMemory()?
答案 0 :(得分:4)
Runtime.freeMemory() javadoc表示返回"an approximation to the total amount of memory currently available for future allocated objects"
所有动态结构的工作方式是它们以块的形式分配内存。当HashMap
变满时,它不会为另外一个对象分配额外的空间。它分配一些大小的块。我不知道它在JVM中的确切工作方式,但它可能会尝试分配它使用的当前内存量的两倍。
答案 1 :(得分:4)
HashMap
类会随着其中的条目数量的增加而调整大小。即使你显示300 + K左边空闲,这可能还不足以处理散列桶的大小调整。
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
// ***possible big allocation here***
Entry[] newTable = new Entry[newCapacity];
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
从更一般的意义上讲,Java中不推荐对堆内存(以及整个进程大小)的细粒度期望。堆中有背景分配以及尚未回收的对象占用您可能没有预料到的空间。此外,垃圾收集器在接近完整堆时逐渐使用越来越多的CPU。您希望以大于预期的最大分配大小的大量内存开销运行。
答案 2 :(得分:1)
在HashMap需要扩展内部存储空间时,您将获得内存不足异常。对此的要求将大于可用的感觉记忆。
答案 3 :(得分:0)
似乎可用内存量不足以运行JVM。