0

如果我不注释第 1 行和第 2 行,则第 1 行会导致 OutOfMemoryError。如果我做相反的事情,它不会导致 OutOfMemoryError,因为 <Key,Value> 包装在 WeakReference 中。但我无法理解第 3 行的输出 ---- i : 3869 Size : 3870 maxSize : 3870

来自 Java 文档:

因为垃圾收集器可能随时丢弃键,所以 WeakHashMap 可能表现得好像一个未知线程正在默默地删除条目。

基于此语句大小应该减少,但第 3 行输出似乎不断增加。为什么这样 ?

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

public class WrongWeakHashMapSize {

private static Map map = new HashMap();

public static void main(String[] args) {
    for (int i = 0, maxSize = 0; i < 10000000L; ++i) {
        /*
         * Line 1 Causes java.lang.OutOfMemoryError: Java heap space Error.
         * After this line i : 244 Size : 490 maxSize : 490.
         */
        map.put(new LargeObject(i), new Integer(i)); // Line 1
        /* After Commenting Line 1 :---- 
         * Line 2 Does not Cause java.lang.OutOfMemoryError. Because of WeakReference class use.I think Line 3
         * is showing wrong Size of MAP. it printed
         * i : 3869 Size : 3870 maxSize : 3870 which seems almost impossible
         * because 3870 objects of LargeObject can not be exist at a time.
         */
        map.put(new WeakReference(new LargeObject(i)), new WeakReference(new Integer(i))); // Line 2
        maxSize = maxSize < map.size() ? map.size() : maxSize; // Line 3
        System.out.println("i : " + i + " Size : " + map.size() + " maxSize : " + maxSize); // Line 4
    }
}

public static class LargeObject {
    private final byte[] space = new byte[1024 * 1024];
    private final int id;

    public LargeObject(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}
}
4

3 回答 3

3

那是因为map.size()为您提供了地图中键值对的数量。weak引用的垃圾收集不会从映射中删除引用,它只会垃圾对象。

will的唯一影响WeakReference是一些LargeObjects 和Integers 将有资格被丢弃,键值映射仍然在映射中,因此仍然被计算在内。

于 2013-03-22T09:56:06.410 回答
0

因为 size 是 map 实现中的 int 字段,并且 GC 在删除 WeakReference 后不会减少它

查看 WeakHashMap#size() 实现的详细信息,WeakHashMap 存储收集的 WeakReferences 队列并按需重新计算大小大小

于 2013-03-22T09:54:48.307 回答
0

来源:http ://weblogs.java.net/blog/2006/05/04/understanding-weak-references 参考队列

一旦 WeakReference 开始返回 null,它指向的对象就变成了垃圾,并且 WeakReference 对象几乎毫无用处。这通常意味着需要进行某种清理;例如,WeakHashMap 必须删除这些失效的条目,以避免持有越来越多的失效 WeakReference。

ReferenceQueue 类使跟踪死引用变得容易。如果将 ReferenceQueue 传递给弱引用的构造函数,则当它指向的对象变为垃圾时,引用对象将自动插入到引用队列中。然后,您可以定期处理 ReferenceQueue 并为死引用执行所需的任何清理。

于 2013-03-22T10:22:23.243 回答