如果我不评论第1行和注释第2行,第1行会导致OutOfMemoryError。如果我反过来,它不会导致OutOfMemoryError,因为< Key,Value>包含在WeakReference中。但我无法理解第3行---- i : 3869 Size : 3870 maxSize : 3870
的输出。
来自Java Docs:
因为垃圾收集器可能随时丢弃密钥,所以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;
}
}
}
答案 0 :(得分:3)
这是因为map.size()
为您提供了地图中键值对的数量。 weak
引用的垃圾收集不会从地图中删除引用,它只会垃圾对象。
WeakReference
的唯一影响是,某些LargeObject
和Integer
s有资格弃置,键值映射仍在地图中,因此仍在计算中。
答案 1 :(得分:0)
因为size是map实现中的int字段,并且GC在删除WeakReference后不会减少它
详细了解WeakHashMap#size()实现, WeakHashMap存储收集的WeakReferences和重新计数大小的队列 按需规模
答案 2 :(得分:0)
来源:http://weblogs.java.net/blog/2006/05/04/understanding-weak-references 参考队列
一旦WeakReference开始返回null,它指向的对象就变成了垃圾,WeakReference对象几乎没用。这通常意味着需要进行某种清理;例如,WeakHashMap必须删除这些已经失效的条目,以避免持有越来越多的死WeakReferences。
ReferenceQueue类可以轻松跟踪死引用。如果将ReferenceQueue传递给弱引用的构造函数,则当它引用的对象变为垃圾时,引用对象将自动插入引用队列。然后,您可以定期处理ReferenceQueue并执行死引用所需的任何清理。