为什么WeakHashMap在GC之后拥有强大的价值参考? [英] Why WeakHashMap holds strong reference to value after GC?

查看:132
本文介绍了为什么WeakHashMap在GC之后拥有强大的价值参考?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

WeakHashMap中的关键对象变得无法访问。并且地图应该在GC之后删除条目。但是对价值对象的强烈提及仍然存在。为什么?

Key object in WeakHashMap became weakly reachable. And map should be remove the entry after GC. But a strong reference to the value object remains. Why?

使用番石榴弱键映射会发现相同的行为。

The same behavior is observed with guava weakkeys map.

预期输出:

...
refKey.get = null
refValue.get = null

但是我得到了输出:

map.keys = []
map.values = []
map.size = 0
refKey.get = null
refValue.get = (123)

代码:

import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
import com.google.common.collect.MapMaker;

public class Test {

    static class Number {
        final int number;
        public Number(int number) { this.number = number; }
        public String toString() { return "(" + number + ")"; }
    }

    static class Key extends Number {
        public Key(int number) { super(number); }
    }

    static class Value extends Number {
        public Value(int number) { super(number); }
    }

    public static void main(String args[]) {

        //Map<Key, Value> map = new MapMaker().weakKeys().makeMap();
        Map<Key, Value> map = new WeakHashMap<>();

        Key key = new Key(1);
        Value value = new Value(123);

        map.put(key, value);

        WeakReference<Key> refKey = new WeakReference<>(key);
        WeakReference<Value> refValue = new WeakReference<>(value);

        key = null;
        value = null;

        System.gc();

        System.out.println("map.keys = " + map.keySet());
        System.out.println("map.values = " + map.values());
        System.out.println("map.size = " + map.size());
        System.out.println("refKey.get = " + refKey.get());
        System.out.println("refValue.get = " + refValue.get());

    }

}

UPD:

我尝试在jСonsole和jcmd中执行GC但输出没有改变。

I tried perform GC in jСonsole and jcmd but output was not changed.

推荐答案

WeakHashMap 包含 Map.Entry 实例,它们使用<引用密钥code> WeakReference (实际上,在OpenJDK / Oracle JDK中,它直接扩展 WeakReference

The WeakHashMap contains Map.Entry instances which reference the key using a WeakReference (actually, in OpenJDK / Oracle JDK, it directly extends WeakReference).

当GC发生时,现在引用缺席键的条目不会从地图中神奇地删除:它们在被清除之前仍然存在,这就是为什么该值仍然存在并具有尚未收集。

When the GC happens, the entries which now reference absent keys are not magically removed from the map: they're still present until cleared, which is why the value is also still present and has not been collected yet.

在OpenJDK中,发生在 expungeStaleEntries() 使用 ReferenceQueue ,并从多个地方调用该方法:

In OpenJDK, that happens in expungeStaleEntries() using a ReferenceQueue, and that method is called from a number of places:


  • size()

  • resize()

  • getTable()本身是从多种方法调用的,包括 get() put()

  • size()
  • resize()
  • getTable() which is itself called from multiple methods, including get() and put()

如果您希望您的值是垃圾收集的,您应该与 WeakHashMap 进行交互,例如通过询问 size()或进行查找。

If you want your value to be garbage collectable, you should interact with the WeakHashMap, e.g. by asking for its size() or doing a lookup.

请注意,这意味着无法收集该值第二次垃圾收集。

Note that it means the value cannot be collected until a second garbage collection.

如果我没记错的话,它在Guava中的工作方式大致相同。

If I remember correctly, it works more or less the same way in Guava.

这篇关于为什么WeakHashMap在GC之后拥有强大的价值参考?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆