How WeakHashMap works under the hood

雨燕双飞 提交于 2019-12-02 10:53:06

Looks like we get (Entry) from queue. I don't know how to explain this

queue.poll() gives you the reference instances you put into the queue through the reference constructor. In this case it's Entry<K,V> extends WeakReference<Object>.

Actually I expect that reference should appear in queue but I could not read something meaningful because object already collected

You get the Reference object itself which you can use to do some cleanup, either through subclassing or by associating it with additional data e.g. through an auxiliary Map. The referee you can obtain through get while it is still alive is not relevant, the Reference object itself is.

The queue returns the very reference object, you have created before. So with your example code, after executing

Reference removedReference = queue.remove();

the expression removedReference == weakRef would evaluate to true, as that’s the only reference object you’ve ever created. With this test, you can already conclude that the object formerly referenced by AAA has been collected, due to the identity of the reference object, so you already read “something meaningful”.

If you want to associate more information with it, a viable way is to create a subclass of WeakReference, which is exactly what WeakHashMap.Entry is about. In its constructor, it calls super(key, queue);, which is not different to your expression new WeakReference(AAA, queue), the first argument specifies the weakly referenced object.

So the garbage collector will enqueue the specialized WeakReference, i.e. Entry, object if its referent (the key) has become unreachable. At this point, the key can’t be retrieved anymore, i.e. its get() method will return null, but the method expungeStaleEntries() isn’t interested in the key anyway. It wants to remove the Entry instance from the table, allowing the garbage collector to reclaim the Entry instance itself and possibly the referenced value, if there are no other reference to it. It helps that this subclass has remembered the previously calculated hash code, so the map doesn’t need to search linearly.

When a ReferenceQueue is polled it will return a Reference object to the referent. The enqueue operation is done by Reference#enqueue which adds this to the queue. Thus, for WeakReference, since it extends Reference the return value can be cast to WeakReference.

So, in the WeakHashMap implementation since the Entry<K, V> extends WeakReference the return value for poll can be cast to Entry<K, V> as it is a subclass of WeakReference which is a subclass of Reference. In other words, the Reference#enqueue will add to queue this thus in the WeakHashMap implementation it will enqueue the instance of Entry<K, V>.

Do note that the class Entry<K, V> doesn't refer to key since it will lead to strong reference and thus GC will not finalize it. It only keeps the hash so that query for get can be executed under normal circumstances i.e. when the key is strongly referenced.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!