WeakReference and its usage

There are two kinds of types in java: primitive and reference. Value types are all primitives. Reference is an object or an array. Almost all object references are strong reference except those wrapped in classes under java.lang.ref package.

Strong type can be GC collected when there’s no reachable path from GC roots to it. But when it comes to WeakReference, the referent T could be collected in next GC run if there’s only WeakReference refers to it. It’s more weaker than strong type. See below example.

import java.lang.ref.WeakReference;

public class WeakRefTest {
  static class Car {
    public String toString() {
      return "A car";
    }
  }

  static class Person extends WeakReference<Car> {
    String name;
    public Person(String name, Car car) {
      super(car);
      this.name = name;
    }
  }

  public static void main(String ...args) {
    Person p1 = new Person("p1", new Car());
    Person p2 = new Person("p2", new Car());
    Car c3 = new Car(); // strong ref to Car
    Person p3 = new Person("p3", c3);
    WeakReference<Car> c = new WeakReference<>(new Car());
    System.gc();
     try {
       Thread.sleep(2000);
     } catch(Exception e) {
       e.printStackTrace();
    }
    System.out.println(c.get() == null); //true
    System.out.println("p1 car");
    System.out.println(p1.get() == null); //true
    System.out.println("p2 car");
    System.out.println(p2.get() == null); //true
    System.out.println("p3 car");
    System.out.println(p3.get() == null); //false
  } 
}

Person has a weak reference of Car. Cars in c, p1, p2 are reclaimed after manual GC as they are all WeakReference, whereas p3 is not. Because the car is not only wrapped in WeakReference but also strong referenced by c3.

A practical example is the Entry class of ThreadLocalMap. The key of the entry is a WeakReference. Thus there will be cases that the Entry is not null but the key is null due to GC. As a result, insert or set in map need to do entry expunge to cope with this situation.

static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }