为什么WeakReference到WeakRef对象不是垃圾回收?

时间:2015-06-04 14:01:43

标签: java garbage-collection

在尝试使用WeakReferences的一些示例时,我只是遇到了以下情况。 我正在创建一个hashmap并在Employee对象上填充一个弱引用。现在我有两个强引用,employee&弱参考。我已经在try块中使两者都为null。在调用gc表达式时,我最终得到块运行。

所以在gc运行之后,它应该在堆中收集weakReference对象,因为没有强引用它,但是当我打印地图时它仍然有指向旧的weakReference对象的键。如何这可能吗?

            Employee employee = new Employee(11);
            WeakReference<Employee>weakReference=new WeakReference<Employee>(employee);
            Map map = new HashMap<WeakReference<Employee>, String>();
            map.put(weakReference, "Test");
            System.out.println(map);

        try {
            employee = null;
            weakReference=null;
            System.gc();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("Inside finally");
        }

        System.out.println(map);

输出是

{java.lang.ref.WeakReference@659e0bfd=Test}
Inside finally
{java.lang.ref.WeakReference@659e0bfd=Test}

2 个答案:

答案 0 :(得分:4)

GC不会删除WeakReference本身,它只会删除它引用的对象,因此map仍会包含WeakReference。你应该检查的是weakReference.get()。这应该在gc()之后返回null。为了以防万一,在检查之前制作一个Thread.sleep(1000),以便GC有一些时间来完成它的工作

答案 1 :(得分:3)

弱引用本身就是强引用的对象,只有它们指向的对象才被弱化。

要在清除引用时收到通知(以便您可以将其从地图中删除),您可以使用ReferenceQueue。这是可选的,因为您可以并且应该始终对访问进行空值检查,但如果永远不会访问它们,则可能导致已填充的WeakReference对象的累积。

必须排空队列,您可以在计时器上或在调用与保存弱引用的数据结构相关的函数时进行排队。

阅读java.lang.ref package description会提供相同的高级概述。