Android強(qiáng)引用潜沦、弱引用枉昏、軟引用

四種引用對(duì)比.png

一、強(qiáng)引用

一個(gè)對(duì)象若持有強(qiáng)引用妄帘,垃圾回收器絕不會(huì)回收它楞黄。當(dāng)內(nèi)存空間不足,Java虛擬機(jī)寧愿拋出OutOfMemoryError錯(cuò)誤抡驼,使程序異常終止鬼廓,也不會(huì)靠隨意回收具有強(qiáng)引用的對(duì)象來(lái)解決內(nèi)存不足的問(wèn)題。

特點(diǎn):
  • 強(qiáng)引用可以直接訪問(wèn)目標(biāo)對(duì)象婶恼。
  • 強(qiáng)引用所指向的對(duì)象在任何時(shí)候都不會(huì)被系統(tǒng)回收桑阶。JVM寧愿拋出OOM異常,也不會(huì)回收強(qiáng)引用所指向的對(duì)象勾邦。
  • 強(qiáng)引用可能導(dǎo)致內(nèi)存泄露蚣录。

java.lang.ref包中提供了幾個(gè)類(lèi):SoftReference、WeakReference眷篇、PhantomReference萎河,分別代表軟引用、弱引用、虛引用虐杯。
ReferenceQueue類(lèi)表示引用隊(duì)列玛歌,它可以和這三種引用類(lèi)聯(lián)合使用,以便跟蹤Java虛擬機(jī)回收所引用的對(duì)象的活動(dòng)擎椰。


二支子、軟引用(SoftReference)

軟引用是除了強(qiáng)引用外,最強(qiáng)的引用類(lèi)型达舒≈蹬螅可以通過(guò)java.lang.ref.SoftReference使用軟引用。

用法:

XXX xxx = new  XXX();
SoftReference ref = new SoftReference(xxx);
XXX anotherXXX = (XXX)ref.get();

如果一個(gè)對(duì)象持有軟引用巩搏,那么如果內(nèi)存空間足夠昨登,垃圾回收器就不會(huì)回收它;如果內(nèi)存空間不足了贯底,就會(huì)回收這些對(duì)象的內(nèi)存丰辣。只要垃圾回收器沒(méi)有回收它,該對(duì)象就可以被程序使用禽捆。

軟引用可用來(lái)實(shí)現(xiàn)內(nèi)存敏感的高速緩存笙什。軟引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果軟引用所引用的對(duì)象被垃圾回收胚想,Java虛擬機(jī)就會(huì)把這個(gè)軟引用加入到與之關(guān)聯(lián)的引用隊(duì)列中得湘。ReferenceQueue中保存的對(duì)象是Reference對(duì)象,而且是已經(jīng)失去了它所軟引用的對(duì)象的Reference對(duì)象顿仇。

ReferenceQueue queue = new  ReferenceQueue();
SoftReference  ref = new  SoftReference(xxx, queue);

利用ReferenceQueue.poll()方法,可以檢查哪個(gè)SoftReference所軟引用的對(duì)象已經(jīng)被回收摆马。于是可以把這些失去軟引用的對(duì)象的SoftReference對(duì)象清除掉臼闻。常用的方式為:

SoftReference ref = null;
while ((ref = (EmployeeRef) q.poll()) != null) {
  // 清除ref
}
示例
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
Drawable drawable = new BitmapDrawable(bitmap);
SoftReference<Drawable> drawableSoftReference = new SoftReference<Drawable>(drawable);
Drawable bgDrawable = drawableSoftReference.get();
if(bgDrawable!= null) {
  view.setBackground(bgDrawable);
}

通過(guò)軟引用的get()方法,取得drawable對(duì)象實(shí)例的強(qiáng)引用囤采,發(fā)現(xiàn)對(duì)象被未回收述呐。在GC在內(nèi)存充足的情況下,不會(huì)回收軟引用對(duì)象蕉毯。

在實(shí)際中乓搬,會(huì)一起從網(wǎng)絡(luò)請(qǐng)求多個(gè)圖片,這時(shí)就會(huì)請(qǐng)求非常多的內(nèi)存空間代虾,導(dǎo)致內(nèi)存吃緊进肯,系統(tǒng)開(kāi)始GC。GC后棉磨,drawables.get()不再返回Drawable對(duì)象江掩,而是返回null,這時(shí)屏幕上背景圖不顯示,在系統(tǒng)內(nèi)存緊張的情況下环形,軟引用被回收策泣。

使用軟引用以后,在OutOfMemory異常發(fā)生之前抬吟,這些緩存的圖片資源的內(nèi)存空間可以被釋放掉的萨咕,從而避免內(nèi)存達(dá)到上限,避免Crash發(fā)生火本。

注意

在垃圾回收器對(duì)Java對(duì)象回收前危队,SoftReference類(lèi)所提供的get方法會(huì)返回Java對(duì)象的強(qiáng)引用,一旦垃圾線程回收該Java對(duì)象之后发侵,get方法將返回null交掏。所以在獲取軟引用對(duì)象的代碼中,一定要判斷是否為null刃鳄,以免出現(xiàn)NullPointerException導(dǎo)致應(yīng)用崩潰盅弛。


三、弱引用(WeakReference)

用法:

WeakReference<XXX> sr = new WeakReference<XXX>(new XXX());

如果一個(gè)對(duì)象持有弱引用叔锐,那么在垃圾回收器線程掃描的過(guò)程中挪鹏,一旦發(fā)現(xiàn)了只具有弱引用的對(duì)象,不管當(dāng)前內(nèi)存空間足夠與否愉烙,都會(huì)回收它的內(nèi)存讨盒。不過(guò),由于垃圾回收器是一個(gè)優(yōu)先級(jí)很低的線程步责,因此不一定會(huì)很快發(fā)現(xiàn)那些只具有弱引用的對(duì)象返顺。

弱引用也可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對(duì)象被垃圾回收蔓肯,Java虛擬機(jī)就會(huì)把這個(gè)弱引用加入到與之關(guān)聯(lián)的引用隊(duì)列中遂鹊。

弱引用與軟引用的根本區(qū)別:

只具有弱引用的對(duì)象擁有更短暫的生命周期,可能隨時(shí)被回收蔗包;
而只具有軟引用的對(duì)象只有當(dāng)內(nèi)存不夠的時(shí)候才被回收秉扑,在內(nèi)存足夠的時(shí)候,通常不被回收调限。

使用場(chǎng)景:

Handler中的使用舟陆,防止內(nèi)存泄露。

軟引用耻矮、弱引用都非常適合來(lái)保存那些可有可無(wú)的緩存數(shù)據(jù)秦躯。如果這樣做,當(dāng)系統(tǒng)內(nèi)存不足時(shí)裆装,這些緩存數(shù)據(jù)會(huì)被回收宦赠,不會(huì)導(dǎo)致內(nèi)存溢出陪毡。而當(dāng)內(nèi)存資源充足時(shí),這些緩存數(shù)據(jù)又可以存在相當(dāng)長(zhǎng)的時(shí)間勾扭。

如何選擇軟引用毡琉、弱引用?

  • 如果只是想避免OutOfMemory異常的發(fā)生妙色,則可以使用軟引用桅滋。
  • 如果對(duì)于應(yīng)用的性能更在意,想盡快回收一些占用內(nèi)存比較大的對(duì)象身辨,則可以使用弱引用丐谋。
  • 還可以根據(jù)對(duì)象是否經(jīng)常使用來(lái)判斷。如果該對(duì)象可能會(huì)經(jīng)常使用的煌珊,就盡量用軟引用号俐;如果該對(duì)象不被使用的可能性更大些,就可以用弱引用定庵。
  • 另外吏饿,和弱引用功能類(lèi)似的是WeakHashMap。WeakHashMap對(duì)于一個(gè)給定的鍵蔬浙,其映射的存在并不阻止垃圾回收器對(duì)該鍵的回收猪落,回收以后,其條目從映射中有效地移除畴博。WeakHashMap使用ReferenceQueue實(shí)現(xiàn)的這種機(jī)制笨忌。

四、虛引用(PhantomReference)

虛引用是所有引用類(lèi)型中最弱的一個(gè)俱病。

一個(gè)持有虛引用的對(duì)象官疲,和沒(méi)有引用幾乎是一樣的,隨時(shí)都可能被垃圾回收器回收亮隙。當(dāng)試圖通過(guò)虛引用的get()方法取得強(qiáng)引用時(shí)袁余,總是會(huì)失敗。并且咱揍,虛引用必須和引用隊(duì)列一起使用,它的作用在于跟蹤垃圾回收過(guò)程棚饵。

當(dāng)垃圾回收器準(zhǔn)備回收一個(gè)對(duì)象時(shí)煤裙,如果發(fā)現(xiàn)它還有虛引用,就會(huì)在垃圾回收后噪漾,銷(xiāo)毀這個(gè)對(duì)象硼砰,將這個(gè)虛引用加入引用隊(duì)列。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末欣硼,一起剝皮案震驚了整個(gè)濱河市题翰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖豹障,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冯事,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡血公,警方通過(guò)查閱死者的電腦和手機(jī)昵仅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)累魔,“玉大人摔笤,你說(shuō)我怎么就攤上這事】研矗” “怎么了吕世?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)梯投。 經(jīng)常有香客問(wèn)我命辖,道長(zhǎng),這世上最難降的妖魔是什么晚伙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任吮龄,我火速辦了婚禮,結(jié)果婚禮上咆疗,老公的妹妹穿的比我還像新娘漓帚。我一直安慰自己,他們只是感情好午磁,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布尝抖。 她就那樣靜靜地躺著,像睡著了一般迅皇。 火紅的嫁衣襯著肌膚如雪昧辽。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天登颓,我揣著相機(jī)與錄音搅荞,去河邊找鬼。 笑死框咙,一個(gè)胖子當(dāng)著我的面吹牛咕痛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播喇嘱,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼茉贡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了者铜?” 一聲冷哼從身側(cè)響起腔丧,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤放椰,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后愉粤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體砾医,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年科汗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了藻烤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡头滔,死狀恐怖怖亭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坤检,我是刑警寧澤兴猩,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站早歇,受9級(jí)特大地震影響倾芝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箭跳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一晨另、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谱姓,春花似錦借尿、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至茄靠,卻和暖如春茂契,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背慨绳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工掉冶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脐雪。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓厌小,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親喂江。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容