Java:OutOfMemoryError异常和freeMemory()

时间:2011-11-18 13:43:09

标签: java exception memory out-of-memory

我有以下测试程序:

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()?

4 个答案:

答案 0 :(得分:4)

  1. Runtime.freeMemory() javadoc表示返回"an approximation to the total amount of memory currently available for future allocated objects"

  2. 所有动态结构的工作方式是它们以块的形式分配内存。当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。