Andrey
Andrey

Reputation: 925

Garbage collector work with 2 WeakHashMaps

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?

Upvotes: 3

Views: 118

Answers (3)

Elia Rohana
Elia Rohana

Reputation: 326

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 +'}';
    }
  }
}

Upvotes: 1

Gaurava Agarwal
Gaurava Agarwal

Reputation: 974

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.

Upvotes: 0

the8472
the8472

Reputation: 43052

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.

Upvotes: 3

Related Questions