Why WeakReference to a WeakRef object is not garbage collected?

852 views Asked by At

While trying out some examples with WeakReferences,I just came across the below scenario. I am creating a hashmap and filled it with a weak reference on Employee object.Now I have two strong references, employee & weakReference . I have made both to null in the try block.Invoking the gc explicity, I get finally block run.

So after the gc run ,it is supposed to collect the weakReference object in the heap ,as there is no strong reference to it,But when I print the map it still has the key pointing to the old weakReference object.How is this possible?

            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);

And the ouput is

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

There are 2 answers

3
Evgeniy Dorofeev On BEST ANSWER

GC will not delete WeakReference itself, it will delete only the object it references, so map will still contain the WeakReference. What you should check is weakReference.get(). This should return null after gc(). Just in case, make a Thread.sleep(1000) before check, so that GC has some time to do its job

0
the8472 On

Weak references themselves are objects which are strongly referenced, only the objects that they point to are weakly held.

To get notified when the reference is cleared (so you can remove it from the map) you can use a ReferenceQueue. This is optional since you can and should always null-check on access, but that may lead to accumulation of nulled-out WeakReference objects if they are never accessed.

The queue has to be drained, which you could do on a timer or when calling functions related to the data-structure holding the weak references.

reading the java.lang.ref package description would have provided the same high level overview.