OutOfMemoryErrors甚至在使用WeakReference用于键和值之后

Ara*_*ram 5 java

下面是我编写的一个小测试,用于教育自己参考API.我以为这永远都不会扔给OOME,但它却扔了它.我无法弄清楚原因.感谢任何帮助.

public static void main(String[] args)
{
    Map<WeakReference<Long>, WeakReference<Double>> weak = new HashMap<WeakReference<Long>, WeakReference<Double>>(500000, 1.0f);

    ReferenceQueue<Long> keyRefQ = new ReferenceQueue<Long>();
    ReferenceQueue<Double> valueRefQ = new ReferenceQueue<Double>();

    int totalClearedKeys = 0;
    int totalClearedValues = 0;

    for (long putCount = 0; putCount <= Long.MAX_VALUE; putCount += 100000)
    {
        weak(weak, keyRefQ, valueRefQ, 100000);

        totalClearedKeys += poll(keyRefQ);
        totalClearedValues += poll(valueRefQ);

        System.out.println("Total PUTs so far    = " + putCount);
        System.out.println("Total KEYs CLEARED so far    = " + totalClearedKeys);
        System.out.println("Total VALUESs CLEARED so far = " + totalClearedValues);
    }

}

public static void weak(Map<WeakReference<Long>, WeakReference<Double>> m, ReferenceQueue<Long> keyRefQ,
        ReferenceQueue<Double> valueRefQ, long limit)
{
    for (long i = 1; i <= limit; i++)
    {
        m.put(new WeakReference<Long>(new Long(i), keyRefQ), new WeakReference<Double>(new Double(i), valueRefQ));
        long heapFreeSize = Runtime.getRuntime().freeMemory();
        if (i % 100000 == 0)
        {
            System.out.println(i);
            System.out.println(heapFreeSize / 131072 + "MB");
            System.out.println();
        }

    }
}

private static int poll(ReferenceQueue<?> keyRefQ)
{
    Reference<?> poll = keyRefQ.poll();
    int i = 0;
    while (poll != null)
    {
        // 
        poll.clear();
        poll = keyRefQ.poll();
        i++;
    }
    return i;

}
Run Code Online (Sandbox Code Playgroud)

}

以下是使用64MB堆运行时的日志

Total PUTs so far    = 0
Total KEYs CLEARED so far    = 77982
Total VALUESs CLEARED so far = 77980
100000
24MB

Total PUTs so far    = 100000
Total KEYs CLEARED so far    = 134616
Total VALUESs CLEARED so far = 134614
100000
53MB

Total PUTs so far    = 200000
Total KEYs CLEARED so far    = 221489
Total VALUESs CLEARED so far = 221488
100000
157MB

Total PUTs so far    = 300000
Total KEYs CLEARED so far    = 366966
Total VALUESs CLEARED so far = 366966
100000
77MB

Total PUTs so far    = 400000
Total KEYs CLEARED so far    = 366968
Total VALUESs CLEARED so far = 366967
100000
129MB

Total PUTs so far    = 500000
Total KEYs CLEARED so far    = 533883
Total VALUESs CLEARED so far = 533881
100000
50MB

Total PUTs so far    = 600000
Total KEYs CLEARED so far    = 533886
Total VALUESs CLEARED so far = 533883
100000
6MB

Total PUTs so far    = 700000
Total KEYs CLEARED so far    = 775763
Total VALUESs CLEARED so far = 775762
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at Referencestest.weak(Referencestest.java:38)
    at Referencestest.main(Referencestest.java:21)
Run Code Online (Sandbox Code Playgroud)

fal*_*tro 3

问题的核心可能是您正在用弱引用对象填充堆,当内存不足时,弱引用会被清除,但引用对象本身却不会,因此您的哈希图充满了船-加载 if WeakReference 对象(更不用说 hashmap 使用的对象数组,它会无限增长),全部指向 null。

正如已经指出的,解决方案是一个弱哈希图,如果这些对象不再使用,它​​将清除它们(这是在放置期间完成的)。

编辑:
正如凯文指出的,您已经解决了引用队列逻辑(我没有给予足够的关注),使用您的代码的解决方案是将其从地图中的关键点处清除集。这正是弱哈希映射的工作原理(轮询只是在插入时触发)。