Java WeakHashMap类

Iga*_*ich 4 java garbage-collection weak-references weakhashmap

我想测试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);
}

}    
Run Code Online (Sandbox Code Playgroud)

运行WeakMapTest类后,我得到以下输出令人不快惊讶:

gc前的地图:{x = x,x1 = x1,x2 = x2} gc后的地图:{x = x,x1 = x1,x2 = x2}

当我预计地图将是空的.

也就是说,垃圾收集器没有完成它的工作.但为什么?

rge*_*man 5

WeakHashMap当垃圾收集器不再可以强烈访问时,它将使其密钥被垃圾收集器回收.

实现说明: WeakHashMap中的值对象由普通的强引用保存.因此,应该注意确保值对象不直接或间接地强烈引用它们自己的密钥,因为这将防止密钥被丢弃.

但是,因为您使用了密钥本身作为值,所以该值仍然可以很强地访问,这意味着垃圾收集器无法回收密钥.

但是,如果您将其他对象用作值,则对键的唯一引用将是键本身.

weakMap.put(x, new Object());
weakMap.put(x1, new Object());
weakMap.put(x2, new Object());
Run Code Online (Sandbox Code Playgroud)

然后,在清除变量并调用垃圾收集器后,我得到了输出:

Map size :3
Map size :0
Map :{}
Run Code Online (Sandbox Code Playgroud)

即使调用System.gc()不能保证垃圾收集器运行,它看起来确实在这里运行.