內(nèi)存優(yōu)化

1.內(nèi)存溢出 out of memory
是指程序在申請(qǐng)內(nèi)存時(shí),沒(méi)有足夠的內(nèi)存空間供其使用汤求,出現(xiàn)out of memory末贾;比如申請(qǐng)了一個(gè)integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出
2.內(nèi)存泄漏 memory leak
是指程序在申請(qǐng)內(nèi)存后,無(wú)法釋放已申請(qǐng)的內(nèi)存空間纤勒,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很?chē)?yán)重隆檀,無(wú)論多少內(nèi)存,都會(huì)被占光摇天。Memory Leak會(huì)最終會(huì)導(dǎo)致Out of Memory粹湃。

常見(jiàn)的內(nèi)存泄漏分為4類(lèi):

  1. 常發(fā)性?xún)?nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼會(huì)被多次執(zhí)行到泉坐,每次被執(zhí)行的時(shí)候都會(huì)導(dǎo)致一塊內(nèi)存泄漏为鳄。
  2. 偶發(fā)性?xún)?nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過(guò)程下才會(huì)發(fā)生腕让。常發(fā)性和偶發(fā)性是相對(duì)的孤钦。對(duì)于特定的環(huán)境,偶發(fā)性的也許就變成了常發(fā)性的纯丸。所以測(cè)試環(huán)境和測(cè)試方法對(duì)檢測(cè)內(nèi)存泄漏至關(guān)重要搔扁。
  3. 一次性?xún)?nèi)存泄漏盗棵。發(fā)生內(nèi)存泄漏的代碼只會(huì)被執(zhí)行一次,或者由于算法上的缺陷,導(dǎo)致總會(huì)有一塊僅且一塊內(nèi)存發(fā)生泄漏唱捣。比如,在類(lèi)的構(gòu)造函數(shù)中分配內(nèi)存滥酥,在析構(gòu)函數(shù)中卻沒(méi)有釋放該內(nèi)存剩岳,所以?xún)?nèi)存泄漏只會(huì)發(fā)生一次。
  4. 隱式內(nèi)存泄漏仇矾。程序在運(yùn)行過(guò)程中不停的分配內(nèi)存庸蔼,但是直到結(jié)束的時(shí)候才釋放內(nèi)存。嚴(yán)格的說(shuō)這里并沒(méi)有發(fā)生內(nèi)存泄漏贮匕,因?yàn)樽罱K程序釋放了所有申請(qǐng)的內(nèi)存朱嘴。但是對(duì)于一個(gè)服務(wù)器程序,需要運(yùn)行幾天粗合,幾周甚至幾個(gè)月萍嬉,不及時(shí)釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存。所以隙疚,我們稱(chēng)這類(lèi)內(nèi)存泄漏為隱式內(nèi)存泄漏壤追。
各個(gè)引用之間的對(duì)比圖

防止內(nèi)存泄漏的主要方法是“引用”
對(duì)象的引用主要分為4個(gè)級(jí)別的:
強(qiáng)引用:GC一般不會(huì)回收具有強(qiáng)引用的對(duì)象。

java中的引用供屉,類(lèi)似于C++的指針行冰。通過(guò)引用,可以對(duì)堆中的對(duì)象進(jìn)行操作伶丐。在某個(gè)函數(shù)中悼做,當(dāng)創(chuàng)建了一個(gè)對(duì)象,該對(duì)象被分配在堆中哗魂,通過(guò)這個(gè)對(duì)象的引用才能對(duì)這個(gè)對(duì)象進(jìn)行操作肛走。


聲明一個(gè)強(qiáng)引用

假設(shè)以上代碼是在方法內(nèi)運(yùn)行的,那么局部變量str將被分配在椔急穑空間上朽色,而對(duì)象StringBuffer實(shí)例邻吞,被分配在堆空間中。局部變量str指向StringBuffer實(shí)例所在的堆空間葫男,通過(guò)str可以操作該實(shí)例抱冷,那么str就是StringBuffer的引用。


內(nèi)存分配

此時(shí)梢褐,運(yùn)行一個(gè)賦值語(yǔ)句:
對(duì)象持有多個(gè)強(qiáng)引用

那么旺遮,str所指向的對(duì)象也將被str1所指向,同時(shí)在局部椨龋空間上會(huì)分配空間存放str1變量耿眉。此時(shí),該StringBuffer實(shí)例就有兩個(gè)引用猪贪。對(duì)引用的”==”操作用于表示兩個(gè)操作數(shù)所指向的堆空間地址是否相同跷敬,不表示兩個(gè)操作數(shù)所指向的對(duì)象是否相等。


多個(gè)強(qiáng)引用

強(qiáng)引用特點(diǎn):
強(qiáng)引用可以直接訪(fǎ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)存泄露拥褂。

軟引用:如果一個(gè)對(duì)象只具有軟引用,那么如果內(nèi)存空間足夠牙寞,GC就不會(huì)回收它饺鹃;如果內(nèi)存空間不足了,就會(huì)回收這些對(duì)象的內(nèi)存间雀。 軟引用可用來(lái)實(shí)現(xiàn)內(nèi)存敏感的高速緩存悔详。

軟引用是除了強(qiáng)引用外,最強(qiáng)的引用類(lèi)型惹挟∏洋Γ可以通過(guò)java.lang.ref.SoftReference使用軟引用。一個(gè)持有軟引用的對(duì)象连锯,不會(huì)被JVM很快回收归苍,JVM會(huì)根據(jù)當(dāng)前堆的使用情況來(lái)判斷何時(shí)回收。當(dāng)堆的使用率臨近閾值時(shí)运怖,才會(huì)回收軟引用的對(duì)象拼弃。 看下我工作中使用到軟引用的場(chǎng)景,加載一個(gè)1080x1920分辨率的圖摇展,約900多K, 對(duì)于我們來(lái)說(shuō)吻氧,這個(gè)圖已是非常大了。


軟引用示例

首先通過(guò)BitmapFactory.decodeStream構(gòu)造一個(gè)大圖bitmap
然后把這個(gè)bitmap轉(zhuǎn)成Drawble類(lèi)型,構(gòu)成強(qiáng)引用医男。
接著使用SoftReference構(gòu)造這個(gè)drawable對(duì)象的軟引用drawables.
最后通過(guò)軟引用的get()方法砸狞,取得drawable對(duì)象實(shí)例的強(qiáng)引用捻勉,發(fā)現(xiàn)對(duì)象被未回收镀梭。在GC在內(nèi)存充足的情況下,不會(huì)回收軟引用對(duì)象踱启。

在實(shí)際中报账,一起請(qǐng)求很多相關(guān)圖片,從網(wǎng)絡(luò)埠偿,這時(shí)就會(huì)請(qǐng)求非常多的內(nèi)存空間透罢,導(dǎo)致內(nèi)存吃緊,系統(tǒng)開(kāi)始會(huì)GC冠蒋。這次GC后羽圃,drawables.get()不再返回Drawable對(duì)象,而是返回null抖剿,這時(shí)屏幕上背景圖不顯示朽寞,說(shuō)明在系統(tǒng)內(nèi)存緊張的情況下,軟引用被回收斩郎。

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

需要注意的是锻煌,在垃圾回收器對(duì)這個(gè)Java對(duì)象回收前妓布,SoftReference類(lèi)所提供的get方法會(huì)返回Java對(duì)象的強(qiáng)引用,一旦垃圾線(xiàn)程回收該Java對(duì)象之后宋梧,get方法將返回null匣沼。所以在獲取軟引用對(duì)象的代碼中,一定要判斷是否為null乃秀,以免出現(xiàn)NullPointerException異常導(dǎo)致應(yīng)用崩潰肛著。

到底什么時(shí)候使用軟引用,什么時(shí)候使用弱引用呢跺讯?
個(gè)人認(rèn)為枢贿,如果只是想避免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è)給定的key驰吓,其映射的存在并不阻止垃圾回收器對(duì)該鍵的回收,回收以后系奉,其條目從映射中有效地移除檬贰。WeakHashMap使用ReferenceQueue實(shí)現(xiàn)的這種機(jī)制。

弱引用:如果一個(gè)對(duì)象只具有弱引用缺亮,那么在垃圾回收器線(xiàn)程掃描的過(guò)程中翁涤,一旦發(fā)現(xiàn)了只具有弱引用的對(duì)象,不管當(dāng)前內(nèi)存空間足夠與否萌踱,都會(huì)回收它的內(nèi)存葵礼。不過(guò),由于垃圾回收器是一個(gè)優(yōu)先級(jí)很低的線(xiàn)程虫蝶,因此不一定會(huì)很快發(fā)現(xiàn)那些只具有弱引用的對(duì)象章咧。

弱引用是一種比軟引用較弱的引用類(lèi)型。在系統(tǒng)GC時(shí)能真,只要發(fā)現(xiàn)弱引用赁严,不管系統(tǒng)堆空間是否足夠,都會(huì)將對(duì)象進(jìn)行回收粉铐。但是疼约,由于垃圾回收器的線(xiàn)程通常優(yōu)先級(jí)很低,因此蝙泼,并一不定能很快的發(fā)現(xiàn)持有弱引用的對(duì)象程剥。這種情況下,弱引用對(duì)象可以存在較長(zhǎng)的一段時(shí)間汤踏。一旦一個(gè)弱引用對(duì)象被垃圾回收器回收织鲸,便會(huì)加入到一個(gè)注冊(cè)引用隊(duì)列中。 看一個(gè)工作中實(shí)例:播放器的播放Panel溪胶,是一個(gè)View搂擦,就是在視頻播放時(shí),可以show哗脖、hide, 也可以拖拽進(jìn)度條之類(lèi)瀑踢,還有上面的音量扳还,亮度調(diào)節(jié)等。這樣一個(gè)view橱夭,我們用弱引用氨距,因?yàn)樵谝曨l播放過(guò)程中,不論硬解還是軟解棘劣,都將占用大量?jī)?nèi)存俏让。保證視頻的渲染效果。 在VideoControllerView.java 有如下一段代碼:


弱應(yīng)用示例

在GC之前呈础,弱引用對(duì)象并未被垃圾回收器發(fā)現(xiàn)舆驶,因此通過(guò)mView.get()方法可以取得對(duì)應(yīng)的強(qiáng)引用橱健。但是只要進(jìn)行垃圾回收而钞,弱引用對(duì)象一旦被發(fā)現(xiàn),便會(huì)立即被回收拘荡,并加入注冊(cè)引用隊(duì)列中臼节。此時(shí),再次通過(guò)mView.get()方法取得強(qiáng)引用就會(huì)失敗珊皿。
注意:軟引用网缝,弱引用都非常適合來(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í)間。

虛引用:一個(gè)持有虛引用的對(duì)象抄淑,和沒(méi)有引用幾乎是一樣的屠凶,隨時(shí)都可能被垃圾回收器回收。

虛引用是所有引用類(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ì)象,獎(jiǎng)這個(gè)虛引用加入引用隊(duì)列只壳。
實(shí)際中幾乎沒(méi)用俏拱,暫不介紹。

在java.lang.ref包中提供了幾個(gè)類(lèi):SoftReference類(lèi)吼句、WeakReference類(lèi)和PhantomReference類(lèi)锅必,它們分別代表軟引用、弱引用和虛引用惕艳。

ReferenceQueue類(lèi)表示引用隊(duì)列搞隐,它可以和這三種引用類(lèi)聯(lián)合使用,以便跟蹤Java虛擬機(jī)回收所引用的對(duì)象的活動(dòng)远搪。

軟引用舉例 1
軟引用舉例 2
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末劣纲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谁鳍,更是在濱河造成了極大的恐慌癞季,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倘潜,死亡現(xiàn)場(chǎng)離奇詭異绷柒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)涮因,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)废睦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人养泡,你說(shuō)我怎么就攤上這事嗜湃。” “怎么了瓤荔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵净蚤,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我输硝,道長(zhǎng)今瀑,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任点把,我火速辦了婚禮橘荠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘郎逃。我一直安慰自己哥童,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布褒翰。 她就那樣靜靜地躺著贮懈,像睡著了一般匀泊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上朵你,一...
    開(kāi)封第一講書(shū)人閱讀 52,255評(píng)論 1 308
  • 那天各聘,我揣著相機(jī)與錄音,去河邊找鬼抡医。 笑死躲因,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的忌傻。 我是一名探鬼主播大脉,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼水孩!你這毒婦竟也來(lái)了镰矿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤荷愕,失蹤者是張志新(化名)和其女友劉穎衡怀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體安疗,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年够委,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荐类。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茁帽,死狀恐怖玉罐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情潘拨,我是刑警寧澤吊输,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站铁追,受9級(jí)特大地震影響季蚂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜琅束,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一扭屁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涩禀,春花似錦料滥、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)高每。三九已至,卻和暖如春践宴,著一層夾襖步出監(jiān)牢的瞬間觉义,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工浴井, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晒骇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓磺浙,卻偏偏與公主長(zhǎng)得像洪囤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子撕氧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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