我想测试Java WeakHashMap类功能,为此我编写了以下测试:
public class WeakHashMapTest {
public static void main(String args[]) {
Map<String, Object> weakMap = new WeakHashMap<>();
String x = new String("x");
String x1 = new String("x1");
String x2 = new String("x2");
weakMap.put(x, x);
weakMap.put(x1, x1);
weakMap.put(x2, x2);
System.out.println("Map size :" + weakMap.size());
// force all keys be eligible
x=x1=x2=null;
// call garbage collector
System.gc();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Map size :" + weakMap.size());
System.out.println("Map :" + weakMap);
}
}
在运行WeakMapTest类之后,我得到以下输出时感到非常惊讶:
gc之前的地图:{x = x,x1 = x1,x2 = x2} gc后的地图:{x = x,x1 = x1,x2 = x2}
当我预计地图将为空时。
也就是说,垃圾收集器没有做它的工作。但为什么?
答案 0 :(得分:5)
当垃圾收集器不再可以强烈访问时,WeakHashMap
将使其密钥被回收。
实施说明: WeakHashMap中的值对象由普通的强引用保存。因此,应该注意确保值对象不直接或间接地强烈引用它们自己的键,因为这样可以防止键被丢弃。
但是,因为您使用了密钥本身作为值,所以仍然可以很容易地访问该值,这意味着垃圾收集器无法回收密钥。
但是,如果您将其他对象用作值,则对键的唯一引用将是键本身。
weakMap.put(x, new Object());
weakMap.put(x1, new Object());
weakMap.put(x2, new Object());
然后,在清除变量并调用垃圾收集器之后,我得到了输出:
Map size :3
Map size :0
Map :{}
即使对System.gc()
的调用并不能保证垃圾收集器运行,看起来它确实在这里运行。
答案 1 :(得分:1)
System.gc()
实际上是建议来运行垃圾收集器。没有保证强制垃圾收集器运行的方法。