javacollectionsweakhashmap

Why is WeakReferenced object not removed by WeakHashMap


I recently tried to understand java.util.WeakHashMap.

But when I use WeakReference to wrap a String, the WeakHash isn't finalizing the Entry.

Also note that I am clearing the WeakReference in the main thread before it is been referred inside the thread method.

When executed, while loop isn't breaking at all!

public class WeakHashMapTotorial
{
    private static Map<String, String> map;

    public static void main(String args[])
    {
        WeakReference<String> s = new WeakReference<String>("Maine");
        map = new WeakHashMap<>();
        map.put(s.get(), "Augusta");

        Runnable runner = new Runnable()
        {
            public void run()
            {
                while (map.containsKey("Maine"))
                {
                    try
                    {
                        Thread.sleep(1000);
                    } catch (InterruptedException ignored)
                    {}
                    System.out.println("Thread waiting");
                    System.gc();
                }
            }
        };
        Thread t = new Thread(runner);
        t.start();
        System.out.println("Main waiting");
        try
        {
            t.join();
        } catch (InterruptedException ignored)
        {}
        s.clear();

    }
}

Solution

  • The Strings that you are using are being held by the pool of interned strings, try the following:

        WeakReference<String> s = new WeakReference<String>(new String("Maine"));
        map = new WeakHashMap<>();
        map.put(s.get(), "Augusta");
    

    This interning effect is described in the Java Language Spec

    Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.