java在JDK1.2以后將對象的引用分為四種級別:強(qiáng)引用 軟引用 弱引用 虛引用魔招。
強(qiáng)引用:
只要引用存在晰搀,垃圾回收器永遠(yuǎn)不會(huì)回收,當(dāng)內(nèi)存空間不足办斑,Java虛擬機(jī)寧愿拋出OutOfMemoryError錯(cuò)誤外恕,使程序異常終止,也不會(huì)靠隨意回收具有強(qiáng)引用的對象來解決內(nèi)存不足的問題乡翅。
Object obj = new Object();
//可直接通過obj取得對應(yīng)的對象 如obj.equels(new Object());
而這樣 obj對象對后面new Object的一個(gè)強(qiáng)引用鳞疲,只有當(dāng)obj這個(gè)引用被釋放之后,對象才會(huì)被釋放掉蠕蚜,這也是我們經(jīng)常所用到的編碼形式尚洽。
軟引用:
如果一個(gè)對象只具有軟引用,則內(nèi)存空間足夠靶累,垃圾回收器就不會(huì)回收它腺毫;如果內(nèi)存空間不足了,就會(huì)回收這些對象的內(nèi)存挣柬。只要垃圾回收器沒有回收它潮酒,該對象就可以被程序使用。軟引用可用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存邪蛔。
軟引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用急黎,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機(jī)就會(huì)把這個(gè)軟引用加入到與之關(guān)聯(lián)的引用隊(duì)列中侧到。
Object obj = new Object();
SoftReference sf = new SoftReference(obj);
obj = null;
sf.get();//有時(shí)候會(huì)返回null
這時(shí)候sf是對obj的一個(gè)軟引用勃教,通過sf.get()方法可以取到這個(gè)對象,當(dāng)然床牧,當(dāng)這個(gè)對象被標(biāo)記為需要回收的對象時(shí)荣回,則返回null;
軟引用主要用戶實(shí)現(xiàn)類似緩存的功能戈咳,在內(nèi)存足夠的情況下直接通過軟引用取值心软,無需從繁忙的真實(shí)來源查詢數(shù)據(jù),提升速度著蛙;當(dāng)內(nèi)存不足時(shí)删铃,自動(dòng)刪除這部分緩存數(shù)據(jù),從真正的來源查詢這些數(shù)據(jù)踏堡。
弱引用:
弱引用與軟引用的區(qū)別在于:只具有弱引用的對象擁有更短暫的生命周期猎唁。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象顷蟆,不管當(dāng)前內(nèi)存空間足夠與否诫隅,都會(huì)回收它的內(nèi)存腐魂。不過,由于垃圾回收器是一個(gè)優(yōu)先級很低的線程逐纬,因此不一定會(huì)很快發(fā)現(xiàn)那些只具有弱引用的對象蛔屹。
弱引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被垃圾回收豁生,Java虛擬機(jī)就會(huì)把這個(gè)弱引用加入到與之關(guān)聯(lián)的引用隊(duì)列中兔毒。
Object obj = new Object();
WeakReference wf = new WeakReference(obj);
obj = null;
wf.get();//有時(shí)候會(huì)返回null
wf.isEnQueued();//返回是否被垃圾回收器標(biāo)記為即將回收的垃圾
弱引用是在第二次垃圾回收時(shí)回收,短時(shí)間內(nèi)通過弱引用取對應(yīng)的數(shù)據(jù)甸箱,可以取到育叁,當(dāng)執(zhí)行過第二次垃圾回收時(shí),將返回null芍殖。
弱引用主要用于監(jiān)控對象是否已經(jīng)被垃圾回收器標(biāo)記為即將回收的垃圾豪嗽,可以通過弱引用的isEnQueued方法返回對象是否被垃圾回收器標(biāo)記。
虛引用:
“虛引用”顧名思義围小,就是形同虛設(shè)昵骤,與其他幾種引用都不同,虛引用并不會(huì)決定對象的生命周期肯适。如果一個(gè)對象僅持有虛引用,那么它就和沒有任何引用一樣成榜,在任何時(shí)候都可能被垃圾回收器回收框舔。
虛引用主要用來跟蹤對象被垃圾回收器回收的活動(dòng)。虛引用與軟引用和弱引用的一個(gè)區(qū)別在于:虛引用必須和引用隊(duì)列 (ReferenceQueue)聯(lián)合使用赎婚。當(dāng)垃圾回收器準(zhǔn)備回收一個(gè)對象時(shí)刘绣,如果發(fā)現(xiàn)它還有虛引用,就會(huì)在回收對象的內(nèi)存之前挣输,把這個(gè)虛引用加入到與之 關(guān)聯(lián)的引用隊(duì)列中纬凤。
Object obj = new Object();
PhantomReference pf = new PhantomReference(obj);
obj=null;
pf.get();//永遠(yuǎn)返回null
pf.isEnQueued();//返回是否從內(nèi)存中已經(jīng)刪除
虛引用是每次垃圾回收的時(shí)候都會(huì)被回收,通過虛引用的get方法永遠(yuǎn)獲取到的數(shù)據(jù)為null撩嚼,因此也被成為幽靈引用停士。
虛引用主要用于檢測對象是否已經(jīng)從內(nèi)存中刪除。
應(yīng)用場景:
軟引用:
軟引用非常適合于創(chuàng)建緩存完丽。當(dāng)系統(tǒng)內(nèi)存不足的時(shí)候恋技,緩存中的內(nèi)容是可以被釋放的。
例如逻族,一個(gè)程序用來處理用戶提供的圖片蜻底。如果將所有圖片讀入內(nèi)存,這樣雖然可以很快的打開圖片聘鳞,但內(nèi)存空間使用巨大薄辅,一些使用較少的圖片浪費(fèi)內(nèi)存空間要拂,需要手動(dòng)從內(nèi)存中移除。如果每次打開圖片都從磁盤文件中讀取到內(nèi)存再顯示出來站楚,雖然內(nèi)存占用較少脱惰,但一些經(jīng)常使用的圖片每次打開都要訪問磁盤,代價(jià)巨大源请。這個(gè)時(shí)候就可以用軟引用構(gòu)建緩存枪芒。
弱引用:
雖然 Java 有垃圾回收機(jī)制,但是只要是自己管理的內(nèi)存谁尸,就應(yīng)該警惕內(nèi)存泄露的問題舅踪,例如對象池、緩存中的過期對象都有可能引發(fā)內(nèi)存泄露的問題良蛮。用 WeakHashMap 來作為緩存的容器可以有效解決這一問題抽碌。WeakHashMap 和 HashMap 幾乎一樣,唯一的區(qū)別就是它的鍵使用弱引用决瞳。當(dāng) WeakHashMap 的鍵標(biāo)記為過期時(shí)货徙,這個(gè)鍵對應(yīng)的條目就會(huì)自動(dòng)被移除。這就避免了內(nèi)存泄漏問題皮胡。