2

As of my understanding HashMap should not be garbage collected and WeakHashMap should be garbage collected but When I'm running this code both hashmap and weakhashmap are being garbage collected.

import java.util.HashMap;
import java.util.WeakHashMap;
public class WeakHashMapDemo {
    public static void main(String[] args) {
        HashMap<String,Temp> hashMap= new HashMap<>();
        hashMap.put("a", new Temp("hashmap"));
        WeakHashMap<String,Temp> weakHashMap= new WeakHashMap<>();
        weakHashMap.put("a", new Temp("identity hashmap"));
        hashMap= null;
        weakHashMap= null;
        System.gc();
        try {
            Thread.sleep(5000);
        }catch(InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        }
        System.out.println(hashMap);
        System.out.println(weakHashMap);
    }
}
class Temp {
    String name;
    Temp(String name) {
        this.name= name;
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println(name+":: Finalize Method Executed");
    }
    @Override
    public String toString() {
        return this.name;
    }
}

Output:

identity hashmap:: Finalize Method Executed
hashmap:: Finalize Method Executed
null
null

While using only HashMap, it is not being garbage collected by the GC.

import java.util.HashMap;
import java.util.WeakHashMap;
public class WeakHashMapDemo {
    public static void main(String[] args) {
        HashMap<String,Temp> hashMap= new HashMap<>();
        hashMap.put("a", new Temp("hashmap"));
        System.gc();
        try {
            Thread.sleep(5000);
        }catch(InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        }
        System.out.println(hashMap);
    }
}
class Temp {
    String name;
    Temp(String name) {
        this.name= name;
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println(name+":: Finalize Method Executed");
    }
    @Override
    public String toString() {
        return this.name;
    }
}

Output:

{a=hashmap}
Shubhamhackz
  • 7,333
  • 7
  • 50
  • 71
  • 2
    you have lots of problems here, using `finalize` which is deprecated (for a reason!) and using `String` as key in `WeakHashMap` - which is again another point for big surprises – Eugene Oct 11 '18 at 12:29
  • 1
    I don't really understand what are you trying to prove here, in your second example you have a strong reference to a non-null `hashMap` via `System.out.println(hashMap);` - so garbage collector absolutely can not reclaim it; unlike your first example – Eugene Oct 11 '18 at 12:33
  • @Eugene ok thanks for pointing but Using String in WeakHashMap can't be responsible for HashMap being garbage collected..Right? – Shubhamhackz Oct 11 '18 at 12:33
  • read my second comment, I don't think I quite understand your point and btw this has *nothing* to do with `WeakHashMap` - it's just basic liveliness of Objects – Eugene Oct 11 '18 at 12:34
  • @Eugene In the first example also I'm providing a strong reference for hashmap...why it is being garbage collected there? – Shubhamhackz Oct 11 '18 at 12:34
  • 3
    because you set it null, explicitly – Eugene Oct 11 '18 at 12:35
  • @Eugene oohh. got it thanks...I missed hashmap= null in second example and didn't realized.. – Shubhamhackz Oct 11 '18 at 12:37
  • 1
    added an answer to capture these comments – Eugene Oct 11 '18 at 12:47

4 Answers4

3

First of all do not use finalize - it has been deprecated, there are better ways to clean after yourself and SO is full of such posts (ReferenceQueue and SoftReferences are among such).

Then don't use objects that are cached internally as keys in WeakHashMap (String is such).

Last point is that this has nothing to do with WeakHashMap, this is basic liveliness of Objects. In your first example you explicitly set the reference to null, thus they are cleared by GC, in your second one you don't, and keep a strong reference to it via System.out.println(hashMap);; thus it will not get collected.

Eugene
  • 117,005
  • 15
  • 201
  • 306
3

In your first example, you set the hashMap variable to null. There is then no reference to the HashMap object anymore, and it can be garbage collected just like any other type of object would. HashMap and WeakHashMap are no different in this regard.

The difference is that the keys in a WeakHashMap may be garbage collected when there are no outside references to them. In a normal HashMap, this won't happen because the map itself holds references to the keys.

Once keys have been collected, the WeakHashMap may clear the entire corresponding entry. this answer goes into more detail about it.

OhleC
  • 2,821
  • 16
  • 29
  • I think you should also explain how an entry gets cleared from a `WeakHashMap` once a key has been collected... – Eugene Oct 11 '18 at 12:48
  • @Eugene that's somewhat more complicated and implementation-dependent, but I've linked another SO answer now. – OhleC Oct 11 '18 at 12:56
1

I think you misunderstood how GC works.

In one sentence: Instances of classes are garbage collected when they are not referenced anymore. It has nothing to do with the type.

This is why is so important to pay attention to the scope of variables. If you keep a reference to an object that you don't need anymore, it won't be collected and you will waste resources.

Also, you are calling System.gc()... You can't programmatically call the GC. It will run according to its own rules. At best, you can "suggest" the JVM that you'd like the GC to run.

I'd advise you to take a look at: https://www.dynatrace.com/resources/ebooks/javabook/how-garbage-collection-works/

Diego
  • 713
  • 5
  • 19
1

At line hashMap= null; you De-Referenced the object of HashMap. In any case after setting the null , on next cycle of Garbage collection it will collected by Garbage Collector.

In second case you are not settting the hashMap to null.

the difference between both of them :

WeakHashMap is an implementation of the Map interface. WeakHashMap is almost same as HashMap except in case of WeakHashMap, if object is specified as key doesn't contain any references- it is eligible for garbage collection even though it is associated with WeakHashMap. i.e Garbage Collector dominates over WeakHashMap.

Khalid Shah
  • 3,132
  • 3
  • 20
  • 39