WeakHashMap垃圾回收原理
介紹
WeakHashMap自然聯(lián)想到的是HashMap。確實(shí),WeakHashMap與HashMap一樣是個(gè)散列表,存儲(chǔ)內(nèi)容也是鍵值對。與HashMap類似的功能就不展開了,本文重點(diǎn)關(guān)注在WeakHashMap是如何做到回收數(shù)據(jù)?
垃圾回收原理
談WeakHashMap回收原理得從WeakReference(弱引用)說起。大家都知道GC回收對象前提是,從根集出發(fā)的引用中沒有有效引用指向該對象,則該對象就可以被回收,這里的有效引用并不包含WeakReference,雖然弱引用可以用來訪問對象,但進(jìn)行垃圾回收時(shí)弱引用并不會(huì)被考慮在內(nèi),僅有弱引用指向的對象仍然會(huì)被GC回收。
那WeakHashMap是如何跟WeakReference關(guān)聯(lián)起來的呢?
我們一起看看實(shí)現(xiàn)的code吧。
大家都知道HashMap實(shí)現(xiàn)里面有個(gè)Entry數(shù)組,WeakHashMap也一樣也有一個(gè)Entry數(shù)組,但是此Entry與彼Entry有些不一樣。WeakHashMap的Entry是繼承WeakReference,這樣一來,整個(gè)Entry就是一個(gè)WeakReference,再來看看Entry的構(gòu)造方法,調(diào)用了super(key, queue),也就是調(diào)用了這個(gè)構(gòu)造方法
WeakReference有兩個(gè)參數(shù),一個(gè)key,一個(gè)是queue,這個(gè)key就是WeakHashMap中存儲(chǔ)的key值,這個(gè)queue是WeakHashMap中創(chuàng)建的ReferenceQueue。
WeakHashMap ReferenceQueue那這個(gè)ReferenceQueue是干嘛的呢?了解GC的朋友可能知道,當(dāng)GC某個(gè)對象時(shí),如果有此對象上還有弱引用與其關(guān)聯(lián),會(huì)將WeakReference對象與Reference類的pending引用關(guān)聯(lián)起來,然后由Reference Handler線程將該插入ReferenceQueue隊(duì)列。
也就是說當(dāng)Entry中的key被GC時(shí),會(huì)將Entry放入到ReferenceQueue中,WeakHashMap就能個(gè)通過ReferenceQueue中的Entry了解到哪些key已經(jīng)被GC,或者即將馬上被GC,起到了通知的作用。
了解了以上信息后,我們再看下面這段代碼:
WeakHashMap expungeStaleEntries
這段代碼就是WeakHashMap用來處理ReferenceQueue中被GC的key所關(guān)聯(lián)的Entry相關(guān)數(shù)據(jù),通過從queue中poll出相關(guān)的Entry,然后去WeakHashMap的entry數(shù)組中找到索引,然后從對應(yīng)的鏈中去掉相關(guān)的Entry,最后將value賦值為空(Help GC),到這里就完成了相關(guān)數(shù)據(jù)的清理。
但是誰來觸發(fā)expungeStaleEntries方法呢?有多個(gè)方法都可以觸發(fā),如put、get、remove、size等方法都能夠觸發(fā)相關(guān)的邏輯。
誤區(qū)
是不是使用了WeakHashMap就一定沒有問題了呢?當(dāng)然不是,如果沒有觸發(fā)expungeStaleEntries這個(gè)方法依然會(huì)導(dǎo)致內(nèi)存泄漏,比如初始化好WeakHashMap中相關(guān)數(shù)據(jù)后,一直不調(diào)用put、get、remove、size等相關(guān)方法,也是不能夠正常回收的。
總結(jié)
了解了WeakHashMap原理之后,使用起來是不是更加得心應(yīng)手了呢。
作者:滌生_YinQi
鏈接:https://www.jianshu.com/p/6904d632549f
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
總結(jié)
以上是生活随笔為你收集整理的WeakHashMap垃圾回收原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HashMap与垃圾回收
- 下一篇: docker镜像、容器以及命令操作