javacollectionshashmapgarbage-collectionweakhashmap

HashMap being garbage collected along with WeakHashMap?


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}

Solution

  • 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.