Why my WeakHashMap entry doesn't be removed by GC?

131 Views Asked by At

I have a class to manage lock objects of several features. I've figured out that WeakHashMap should fit my requirement. Here is my code:

public static class FeatureLockManager {
        private final Map<Object, WeakKeyLockPair> locks;
        private String domain;

        public FeatureLockManager(String domain) {
            this.domain = domain;
            locks = new WeakHashMap<Object, WeakKeyLockPair>();
        }

        public Lock getLock(Object feature) {
            if (locks.get(feature) == null) {
                synchronized (locks) {
                    locks.computeIfAbsent(feature, l -> new WeakKeyLockPair(feature, new ReentrantLock()));
                }
            }
            return locks.get(feature);
        }

        private static class WeakKeyLockPair implements Lock {
            private final Reference<Object> feature;
            private final Lock lock;

            private WeakKeyLockPair(Object feature, Lock lock) {
                this.feature = new WeakReference<Object>(feature);
                this.lock = lock;
            }
...      }
       }

However, after making a simple test, I realized that lock object won't be removed after GC.

public static void main(String[] args) throws InterruptedException {
        FeatureLockManager test = new FeatureLockManager("test");
        Lock lock = test.getLock("add user");
        System.out.println(lock.hashCode());
        // do thing
        System.gc();
        Thread.sleep(1000);
        Lock lock1 = test.getLock("add user");
        System.out.println(lock1.hashCode());
        System.out.println(lock1 == lock);
    }

Could you please tell me that what's wrong with my implementation? Thank you in advance!

2

There are 2 best solutions below

2
Brijesh Bhatt On BEST ANSWER

According to the java documentation of the WeakHashMap

Each key object in a WeakHashMap is stored indirectly as the referent of a weak reference. Therefore a key will automatically be removed only after the weak references to it, both inside and outside of the map, have been cleared by the garbage collector.

Your FeatureLockManager class still has a strong reference to the key element ("add user") of the WeakHashMap.

For more details, check the documentation

0
Anas Ablan On

I think that is because you are using String as a key in your map, Strings are stored in the general string pool memory, and the same literal value would be used by different parts of the program so it won't become eligible for GC, I would recommend using different object type or primitive wrapper types (try integer representation for instance) or any other object other than string