文章目錄
強引用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大引用小總結
可以進入gcroot 集合的對象: