【问题标题】:Java WeakHashMap ClassJava WeakHashMap 类
【发布时间】:2015-01-06 01:31:46
【问题描述】:

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

当我预计地图将为空时。

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

【问题讨论】:

    标签: java garbage-collection weak-references weakhashmap


    【解决方案1】:

    WeakHashMap 的密钥将在它们不再强可达时被垃圾收集器回收。

    实现说明: WeakHashMap 中的值对象由普通的强引用持有。因此,应注意确保值对象不会直接或间接地强烈引用自己的键,因为这会防止键被丢弃。

    但是,因为你使用了key本身作为value,所以value仍然是强可达的,这意味着垃圾收集器无法回收key。

    但是,如果您使用其他对象作为值,那么对键的唯一引用将是键本身。

    weakMap.put(x, new Object());
    weakMap.put(x1, new Object());
    weakMap.put(x2, new Object());
    

    然后,在清除变量并像您已经完成的那样调用垃圾收集器之后,我得到了输出:

    Map size :3
    Map size :0
    Map :{}
    

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

    【讨论】:

    • 当我将上面演示的代码与 new Object() 一起使用时,它确实可以正常工作,但是当我想要在键和值具有相同引用时设置实现之类的东西时我应该怎么做?跨度>
    • 我不知道任何 JDK 提供的类会为 Sets 提供类似 WeakHashMap 的行为。
    • @IgalIsra 那么你可能想要Guava's Interner
    【解决方案2】:

    System.gc() 实际上是运行垃圾收集器的建议。没有保证强制垃圾收集器运行的方法。

    【讨论】:

    猜你喜欢
    • 2019-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多