3

I have cache, implemented with WeakHashMap, like this:

private static WeakHashMap<Object, WeakReference<Object>> objects = new WeakHashMap<>();

I have an instance of class City:

City c = new City();

I now add this instance to my map like this:

objects.put(c, new WeakReference<Object>(c));

According to WeakHashMap jvm implementation, if key doesn't have strong references to it, it's deleted from the map (in its free time).
So, if my object 'c' is not used in the program anymore, it will be deleted from 'objects' map.
So far, so good.

But what happens if I have two maps?

private static WeakHashMap<Object, WeakReference<Object>> objects1 = new WeakHashMap<>();
private static WeakHashMap<Object, WeakReference<Object>> objects2 = new WeakHashMap<>();
City c = new City();
objects1.put(c, new WeakReference<Object>(c));
objects2.put(c, new WeakReference<Object>(c));

Will GC collect the object 'c' in this case?

Andrey
  • 853
  • 9
  • 27
  • If the Grim Reaper decides to reap an object, **all** weak-references to it will be appropriately nullified. – Mike Robinson Jul 07 '16 at 15:35
  • why are you wrapping the value of the HashMap in WeakReference ? you shouldn't do this, you could have null values in this case – Elia Rohana Jul 07 '16 at 16:18
  • @EliaRohana It can't be null as long as it's used somewhere else. – Andrey Jul 07 '16 at 16:37
  • @AndreyP you are right, but for what reason you want to have WeakReference Values? having Keys with null values ? in my opinion its bad practice – Elia Rohana Jul 07 '16 at 16:43
  • @EliaRohana In reality there's more complicated task. For this example values may be whatever (GC collectable). – Andrey Jul 07 '16 at 16:49

3 Answers3

3

Take a piece of paper, draw a graph with the objects as vertices, references as edges.

If you can't find a path of strong edges from a GC root (e.g. static field or local variable on the stack) to the object in equestion then it is not strongly reachable and thus eligible for GC.

the8472
  • 40,999
  • 5
  • 70
  • 122
1

For Sure it will collect it(when GC starts), because its still referenced by WeakReference and not a Strong reference, not matter how many WeakReferences are referencing it.

You can read about WeakReference here : WeakReference

Here is an Example to demonstrate it:

public class WeakHashMapExample {

  //strongly reference key to prevent GC from collecting it
  private static final Key stronglyRefKey1 = new Key(1);

  public static void main(String[] args) throws InterruptedException {

    WeakHashMap<Key, String> cache1 = new WeakHashMap<>();
    WeakHashMap<Key, String> cache2 = new WeakHashMap<>();

    //adding same keys
    Key key2 = new Key(2);
    cache1.put(stronglyRefKey1, "val 1");
    cache1.put(key2, "val 2");
    cache2.put(stronglyRefKey1, "val 1");
    cache2.put(key2, "val 2");
    key2 = null; // remove strong reference

    //may or may not print Key(2) key, depends if GC starts at this point
    System.out.println("cache1 = " + cache1);
    System.out.println("cache2 = " + cache2);

    //for GC to start so all weak reference should be cleared
    System.gc();

    //after GC ha been ran, key(2) will be removed because its only referenced by weak reference of the WeakHashMap
    System.out.println("cache1 = " + cache1);
    System.out.println("cache2 = " + cache2);
  }

  private static class Key{
    int value;

    private Key(int value) {
      this.value = value;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      Key key = (Key) o;

      if (value != key.value) return false;

      return true;
    }

    @Override
    public int hashCode() {
      return value;
    }

    @Override
    public String toString() {
      return "Key{value=" + value +'}';
    }
  }
}
Elia Rohana
  • 326
  • 3
  • 16
  • In the example above you used 2 different instances for Key(2). What if it was the same instance? If WeakHashMap has strong ref to key, GC will not collect Key(2). – Andrey Jul 07 '16 at 16:43
  • i does not matter if the same instance or not, the key thing here its not referenced from any strong reference so its eligible for GC. i edited the code above to use the same instance – Elia Rohana Jul 07 '16 at 16:54
0

Weak is weak, it won't become strong if it is joined by another weak.

It will be garbage collected if no other strong reference. No doubt.

Gaurava Agarwal
  • 974
  • 1
  • 9
  • 32