文章目錄
- 強引用Referrnce
-
- 整體架構
- 強引用(預設支援)
- 軟引用
- 弱引用
- 軟引用和弱引用的适用場景
- weakhashmap案例示範和解析
- 虛引用簡介
-
- 引用隊列
- ReferenceQueue引用隊列簡介
- 虛引用PhantomReference
- GCRoots和4大引用小總結
強引用Referrnce
絕大多數情況下用到的是強引用,軟引用在緩存場景中出現。
整體架構
以前我們說的引用就是用到了Reference這一層。他就是強引用。他所在的包是java.lang.ref,如下圖:
強引用(預設支援)
示範案例:
運作結果:
軟引用
強引用:死了都不收。軟引用:記憶體足夠的情況下,我不收,記憶體不夠的情況下,我要收。
代碼示範:
此時記憶體是夠用的,軟引用不會被回收,效果如下:
為了示範效果(記憶體不夠用時,軟引用會被回收),先設定一下jvm參數,改小。
運作效果:
此時會發現,軟引用就被回收了。
弱引用
弱引用:不管記憶體是否夠用,隻要觸發gc,一定被回收。
代碼示例:
運作結果:
會發現,記憶體足夠的情況下,發生gc,直接殺掉弱引用對象。
軟引用和弱引用的适用場景
假設有個讀圖檔的場景,肯定要用緩存,第一次讀的慢,以後就快了。但是圖檔比文字大,加載到記憶體空間裡面,很容易就滿了。
容易觸發oom。
mybatis緩存的部分,大面積的使用了軟引用。
weakhashmap案例示範和解析
檢視你一下api文檔,它位于util包:
官方介紹
hashtable實作了map接口,使用“弱key”,map中的entry将會被自動移除當他的key不再被正常的引用之後。對于給定的映射的key,不會像hashmap一樣阻止gc對它回收。當一個key被回收之後,鍵值對就無效了。效果就相當于被從map中移除。
案例解釋:
這裡把key置空,map裡面的資料沒有影響。是因為底層源碼在put的時候,轉化為放入了Node對象(含有kv),是以列印是沒有問題的。
基于上面的實驗,觸發gc:
運作結果如下:資料還在。這種情況下,map裡面的資料是強引用,不會被回收的。
同樣的方法,再測試一下弱hashmap,代碼如下:
運作結果:
因為是弱引用:隻要觸發gc就回收,是以最後列印結果就沒了。發生oom的機率會大大降低。
這種類友善我們做高速緩存和對記憶體敏感的業務場景。
虛引用簡介
虛引用又稱為幽靈引用。
類繼承結構圖:
引用隊列
虛引用被回收之前,要被引用隊列儲存一下。
ReferenceQueue引用隊列簡介
代碼示例:
運作結果:
gc之前沒有,gc之後反而進了隊列了。
虛引用被回收之前,要被引用隊列儲存一下。利用這個api,weakreference也可以。
虛引用PhantomReference
虛引用是監控一個對象的回收資訊,然後回收之前把他放到referencequeue中儲存一下。類似spring aop的後置通知。
看下面代碼就可以明白:
列印檢視回收情況:
gc之前,虛引用每次get都是null,gc之後,get還是null,但是就被放到引用隊列裡面了。
GCRoots和4大引用小總結