內(nèi)存泄漏與內(nèi)存溢出

1.內(nèi)存泄漏

  • 內(nèi)存泄漏(Memory Leak)是指程序中己動態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費黎炉,導(dǎo)致程序運行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。
  • 生活例子:打網(wǎng)球醋拧,打飛了的球沒去撿或飛的太遠(yuǎn)撿不回來了
  • 內(nèi)存泄漏是導(dǎo)致內(nèi)存溢出的原因之一;內(nèi)存泄漏累積起來就會造成內(nèi)存溢出
  • 內(nèi)存泄漏可以通過完善代碼來避免
  • 一般我們所說的內(nèi)存泄漏指的是堆內(nèi)存的泄露,堆內(nèi)存是指程序從堆中分配的,大小隨機(jī)的用完后必須顯示釋放的內(nèi)存丹壕,C++/C中有free函數(shù)可以釋放內(nèi)存庆械,java中有垃圾回收機(jī)制不用程序員自己手動調(diào)用釋放

2.內(nèi)存溢出

  • 內(nèi)存溢出(Out Of Memory,簡稱OOM)是指應(yīng)用系統(tǒng)中存在無法回收的內(nèi)存或使用的內(nèi)存過多菌赖,最終使得程序運行要用到的內(nèi)存大于能提供的最大內(nèi)存缭乘。
  • 生活例子 : 水杯滿了還往里面加水
  • 內(nèi)存溢出可以通過調(diào)整配置來減少發(fā)生頻率,無法徹底避免

3.內(nèi)存泄漏的原因:

以發(fā)生的方式來分類,內(nèi)存泄漏可以分為4類:

  • 常發(fā)性內(nèi)存泄漏 : 發(fā)生內(nèi)存泄漏的代碼會被多次執(zhí)行到,每次被執(zhí)行的時候都會導(dǎo)致一塊內(nèi)存泄漏琉用。
  • 偶發(fā)性內(nèi)存泄漏 : 發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會發(fā)生堕绩。常發(fā)性和偶發(fā)性是相對的。對于特定的環(huán)境邑时,偶發(fā)性的也許就變成了常發(fā)性的奴紧。所以測試環(huán)境和測試方法對檢測內(nèi)存泄漏至關(guān)重要。
  • 一次性內(nèi)存泄漏 : 發(fā)生內(nèi)存泄漏的代碼只會被執(zhí)行一次晶丘,或者由于算法上的缺陷黍氮,導(dǎo)致總會有一塊僅且一塊內(nèi)存發(fā)生泄漏。比如浅浮,在類的構(gòu)造函數(shù)中分配內(nèi)存沫浆,在析構(gòu)函數(shù)中卻沒有釋放該內(nèi)存,所以內(nèi)存泄漏只會發(fā)生一次滚秩。
  • 隱式內(nèi)存泄漏 : 程序在運行過程中不停的分配內(nèi)存专执,但是直到結(jié)束的時候才釋放內(nèi)存。嚴(yán)格的說這里并沒有發(fā)生內(nèi)存泄漏郁油,因為最終程序釋放了所有申請的內(nèi)存本股。但是對于一個服務(wù)器程序,需要運行幾天已艰,幾周甚至幾個月痊末,不及時釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存。所以哩掺,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏凿叠。(重視)

總結(jié):從用戶使用程序的角度來看,內(nèi)存泄漏本身不會產(chǎn)生什么危害嚼吞,作為一般的用戶盒件,根本感覺不到內(nèi)存泄漏的存在。真正有危害的是內(nèi)存泄漏的堆積舱禽,這會最終消耗盡系統(tǒng)所有的內(nèi)存炒刁。從這個角度來說,一次性內(nèi)存泄漏并沒有什么危害誊稚,因為它不會堆積翔始,而隱式內(nèi)存泄漏危害性則非常大,因為較之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測到城瞎。

4.內(nèi)存溢出的原因及解決方法:

內(nèi)存溢出原因:

  • 內(nèi)存中加載的數(shù)據(jù)量過于龐大,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù)飒箭;
  • 集合類中有對對象的引用蜒灰,使用完后未清空,使得JVM不能回收强窖;
  • 代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對象實體;
  • 使用的第三方軟件中的BUG削饵;
  • 啟動參數(shù)內(nèi)存值設(shè)定的過小
    內(nèi)存溢出的解決方法:
  • 修改JVM啟動參數(shù)未巫,直接增加內(nèi)存窿撬。(-Xms,-Xmx參數(shù)一定不要忘記加叙凡。)
  • 檢查錯誤日志劈伴,查看“OutOfMemory”錯誤前是否有其 它異常或錯誤握爷。
  • 對代碼進(jìn)行走查和分析跛璧,找出可能發(fā)生內(nèi)存溢出的位置。
  • 使用內(nèi)存查看工具動態(tài)查看內(nèi)存使用情況新啼。

重點排查以下幾點:
1追城、檢查對數(shù)據(jù)庫查詢中,是否有一次獲得全部數(shù)據(jù)的查詢燥撞。一般來說座柱,如果一次取十萬條記錄到內(nèi)存,就可能引起內(nèi)存溢出物舒。這個問題比較隱蔽色洞,在上線前,數(shù)據(jù)庫中數(shù)據(jù)較少冠胯,不容易出問題火诸,上線后,數(shù)據(jù)庫中數(shù)據(jù)多了荠察,一次查詢就有可能引起內(nèi)存溢出置蜀。因此對于數(shù)據(jù)庫查詢盡量采用分頁的方式查詢奈搜。
2、檢查代碼中是否有死循環(huán)或遞歸調(diào)用盯荤。
3媚污、檢查是否有大循環(huán)重復(fù)產(chǎn)生新對象實體。
4廷雅、檢查List航缀、MAP等集合對象是否有使用完后芥玉,未清除的問題。List揽涮、MAP等集合對象會始終存有對對象的引用盾似,使得這些對象不能被GC回收零院。

5.如何避免內(nèi)存泄漏?

1嵌牺、在涉及使用Context時拟蜻,對于生命周期比Activity長的對象應(yīng)該使用Application的Context酝锅。凡是使用Context優(yōu)先考慮Application的Context爸舒,當(dāng)然它并不是萬能的扭勉,對于有些地方則必須使用Activity的Context液走。對于Application,Service网梢,Activity三者的Context的應(yīng)用場景如下:
其中拣宰,NO1表示Application和Service可以啟動一個Activity巡社,不過需要創(chuàng)建一個新的task任務(wù)隊列重贺。而對于Dialog而言气笙,只有在Activity中才能創(chuàng)建潜圃。除此之外三者都可以使用谭期。
2隧出、對于需要在靜態(tài)內(nèi)部類中使用非靜態(tài)外部成員變量(如:Context、View )凄诞,可以在靜態(tài)內(nèi)部類中使用弱引用來引用外部類的變量來避免內(nèi)存泄漏帆谍。
3烈涮、對于不再需要使用的對象跃脊,顯示的將其賦值為null,比如使用完Bitmap后先調(diào)用recycle()翠储,再賦為null援所。
4、保持對對象生命周期的敏感滔岳,特別注意單例、靜態(tài)對象禽拔、全局性集合等的生命周期硫惕。
5恼除、對于生命周期比Activity長的內(nèi)部類對象缚柳,并且內(nèi)部類中使用了外部類的成員變量秋忙,可以這樣做避免內(nèi)存泄漏:

  • 將內(nèi)部類改為靜態(tài)內(nèi)部類
  • 靜態(tài)內(nèi)部類中使用弱引用來引用外部類的成員變量

6.如何檢查和分析內(nèi)存泄漏堵幽?

因為內(nèi)存泄漏是在堆內(nèi)存中朴下,所以對我們來說并不是可見的殴胧。通常我們可以借助MAT、LeakCanary等工具來檢測應(yīng)用程序是否存在內(nèi)存泄漏灸姊。
1力惯、MAT是一款強大的內(nèi)存分析工具,功能繁多而復(fù)雜诱建。
2俺猿、LeakCanary則是由Square開源的一款輕量級的第三方內(nèi)存泄漏檢測工具,當(dāng)檢測到程序中產(chǎn)生內(nèi)存泄漏時谊惭,它將以最直觀的方式告訴我們哪里產(chǎn)生了內(nèi)存泄漏和導(dǎo)致誰泄漏了而不能被回收豹芯。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市握牧,隨后出現(xiàn)的幾起案子沿腰,更是在濱河造成了極大的恐慌颂龙,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件押赊,死亡現(xiàn)場離奇詭異饺藤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)流礁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門涕俗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人神帅,你說我怎么就攤上這事再姑。” “怎么了找御?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵遇革,是天一觀的道長旋恼。 經(jīng)常有香客問我冬殃,道長,這世上最難降的妖魔是什么难捌? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任圣蝎,我火速辦了婚禮从隆,結(jié)果婚禮上辛燥,老公的妹妹穿的比我還像新娘榴都。我一直安慰自己柴信,他們只是感情好窃判,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布舆瘪。 她就那樣靜靜地躺著召调,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上办素,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天庄吼,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播存谎,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼遍略,長吁一口氣:“原來是場噩夢啊……” “哼履因!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盹愚,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤栅迄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后皆怕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毅舆,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年愈腾,在試婚紗的時候發(fā)現(xiàn)自己被綠了憋活。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡顶滩,死狀恐怖余掖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情礁鲁,我是刑警寧澤盐欺,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站仅醇,受9級特大地震影響冗美,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜析二,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一粉洼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叶摄,春花似錦属韧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至会傲,卻和暖如春锅棕,著一層夾襖步出監(jiān)牢的瞬間拙泽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工裸燎, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留顾瞻,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓德绿,卻偏偏與公主長得像荷荤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子移稳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

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