In weakHashMap if i update or change the previously stored key object, the garbage Collector deletes the key value pair

221 Views Asked by At

I have stored an object as a key in WeakHashMap. Now if I change its value and then call the GC and print map, then nothing is there.

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

    WeakHashMap map = new WeakHashMap();
    Integer obj = new Integer(200);
    map.put(obj, "sgdjsgd");
    obj=new Integer(20);
    System.gc();
    Thread.sleep(2000);
    System.out.println(map);
}
  • expected output: {200,"sgdjsgd"}
  • atual output: {}
5

There are 5 best solutions below

1
user2342558 On

With this code you are changing the pointer in the memory that is stored in obj:

obj=new Integer(20);

Before this line, obj held a pointer reference to new Integer(200);

Now, instead, obj holds a pointer reference to new Integer(20); which is different from the previous in the memory.

Therefore, because WeakHashMap holds a weak reference, when the garbage collector runs it collect the object referenced by the map, so when you print the map it shows {} because the pointer saved in the map's key is no more found.

0
JArgente On

I am not sure what are you trying to do but What I see in your code is that you assign a new object to a reference that previosly was pointing to a key in the WeakHashMap, by doing that, the original key (Integer(200)) has none pointer so It is useless because you never can reach that key so it is logical that gc will dispose it

2
imkiva On

WeakHashMap may behave as though an unknown thread is silently removing entries.

The WeakHashMap.Entry is a WeakReference object whose referent is the key object you passed to map.put(). That's to say if the key becomes weakly reachable, the garbage collector will atomically declare it finalizable.

The Java SE 8 document says that:

An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.

In this line of your code

    Integer obj = new Integer(200);
    map.put(obj, "sgdjsgd");

the obj is a strong refernce to the integer object created by new Integer(200) and then it is passed to map.put() which creates a WeakReference (assuming it's called w) to hold this integer object.

But after this line:

obj = new Integer(20);

The obj points to another integer object that holds 20 (the w still points to the integer object that holds 200). But changing the object the obj points to will make the referent of w becomes weakly reachable because it can only be reached by traversing a weak reference (namely the w).

When control returns from the method call to System.gc(), the JVM has made its best effort to recycle all discarded objects. So as is said above, the garbage collector will atomically declare weakly-reachable objects finalizable and finally clear them.

So the w is cleared, the entry in the map is discarded by the garbage collector and as a result, your map contains nothing.

0
Anonymous On

user207421 put it very precisely: Your code is working exactly as designed. It’s not clear to me exactly how you have come to expect something else, but I would like to point out:

  • Your code does not alter anything inside the map. Assigning a new value, 20, to obj only changes that variable. The key in the map is still the Integer holding the value 200.
  • The assignment of 20 to obj makes sure that there are no other references to the key 200 in the map, which is why the garbage collector is allowed to remove that key from the map.

If you wanted to alter the key in the map: don’t ever. A hash map, including a WeakHashMap, stores objects by their hash code. Altering a key object most likely changes the hash code. So the map will not be able to find the key again even though it is in there. If you need this functionality, you must first remove the key from the map and then insert the new key:

    String value = map.remove(obj);
    obj = Integer.valueOf(20);
    map.put(obj, value);

With this change to your code I get this output:

{20=sgdjsgd}

0
sonu kumar On
Integer obj = new Integer(200);

This creates a strong reference by default to Integer object obj ----strong reference ---->200

map.put(obj, "sgdjsgd");

obj ----weak reference ----->200
Now Integer object 200 has both strong and weak reference so it is not eligible for GC

obj=new Integer(20);

obj ----strong reference---->20

obj-----X----->200 obj ----weak reference--->200

Here the existing strong reference to 200 has been lost. So Integer object 200 is only left with weak reference and will be eagerly collected by GC.

And because of this the key also gets deleted from weakHashMap

Check out this link for more details http://www.fis.unipr.it/lca/tutorial/java/refobjs/about/weak.html