android 內存泄漏和內存溢出

內存溢出(out of memory)

OOM指當前對象的內存占用已經(jīng)超出分配內存的大小,這時未處理的異常就會拋出。過多的內存泄露會導致內存溢出,造成程序崩潰

造成內存溢出的原因:

1.內存泄漏導致;2.占用內存比較多的對象

如常見的內存溢出:

bitmap過大(顯示像素過高或者圖片尺寸遠遠大于顯示空間尺寸時。通常要將bitmap縮放,減少暫占用內存);

引用沒釋放(長時間保持某些資源的引用,導致GC(garbage collection垃圾回收)無法回收,該對象占用的內存就無法被使用。如activity被引用,在調用finish()之后卻沒有釋放,第二次打開又重新創(chuàng)建,這樣的內存泄露不斷發(fā)生,就會導致內存的溢出);

資源對象沒關閉(Cursor/file等資源,會在finalize中關閉,但效率過低,易造成內存泄漏;SQLiteCurost當數(shù)據(jù)量大的時候容易泄漏);

內存泄漏(memory leak)

有一些對象只有有限的生命周期。當它們的任務完成了之后,將會被GC回收。如果在對象的生命周期本該結束的時候,還被一系列的引用,就會導致內存泄漏。隨著泄漏的累積,app將消耗完內存。
如Activity.onDestory()被調用之后,view樹和bitmap應該都被GC回收。如果一個正在運行的后臺線程繼續(xù)持有這個activity的引用,那么相關的內存將不會被回收,最終導致out OfMemoryError崩潰。
memory leak最終會導致OOM
內存泄漏的原因:
1.資源對象沒關閉、集合類內存泄漏(資源對象沒關閉:Cursor/file等資源,會在finalize中關閉,但效率過低,易造成內存泄漏;SQLiteCurost當數(shù)據(jù)量大的時候容易泄漏),屬性動畫在activity onDestory()的時候 animator.cancel()來停止動畫

2.使用adapter時沒有使用系統(tǒng)緩存的converview

3.沒有及時調用recycle()釋放不再使用的bitmap(釋放之后建議bitmap= null;避免GC回收過慢等原因)

4.上下文的context用的是activity或者fragment。因此要使用application的context來代替activity相關的context,否則會在activity、fragment銷毀時也不會銷毀其內存(不要讓生命周期長于activity的對象持有activity的引用)
在以下情況下不可以使用application
a.對話框創(chuàng)建的上下文
b.跳轉到其它activity的上下文
c.創(chuàng)建布局layout或view要用到的上下文

5.廣播注冊沒取消造成的內存泄漏

6.handler應該申請為static對象,并且在內部類中保存一個對外部類的弱引用

內存泄漏的分類:

1.常發(fā)性內存泄漏:發(fā)生內存泄漏的代碼會被多次執(zhí)行,每次執(zhí)行都會導致一塊內存泄漏

2.偶發(fā)性內存泄漏:發(fā)生內存泄漏的代碼只有在特定環(huán)境或操作過程中才會發(fā)生。常發(fā)性和偶發(fā)性是相對的。對于特定的環(huán)境,偶發(fā)性可能會變成常發(fā)性。因此測試環(huán)境和測試方法對檢測內存泄漏尤其重要

3.一次性內存泄漏:發(fā)生內存泄漏的代碼只會執(zhí)行一次,或者由于算法上的缺陷,導致總有一塊僅且有一塊內存發(fā)生泄漏。如在類的構造函數(shù)中分配內存,在析構函數(shù)中卻沒有釋放該內存,導致內存泄漏只會發(fā)生一次

4.隱私內存泄漏:程序在運行過程中不停地分配內存。但是在結束的時候才釋放內存。嚴格來說并沒有發(fā)生內存泄漏,因為程序最終還是釋放了所有的內存。但是對于一個服務程序。需要運行幾天甚至幾個月。不及時釋放內存也可能導致最終耗盡所有的內存。稱這種內存泄漏為隱私內存泄漏

內存泄漏和內存溢出都不能通過try catch處理

內存泄漏的檢測工具:leakcanary
參考來源

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。