Android 內存泄漏分析

為什么會內存泄漏?

一個不會被使用的對象,因為另一個正在使用的對象持有該對象的引用,導致它不能正常被回收,而停留在堆內存中,內存泄漏就產生了;

 

引用分類:

1.強引用

以前我們使用的大部分引用實際上都是強引用,這是使用最普遍的引用。例如使用new創建對象 ,匿名內部類/非靜態內部類和異步線程,默認都會持有外界的引用;

2.軟引用(SoftReference)

如果一個對象只具有軟引用,那就類似于可有可物的生活用品。如果內存空間足夠,垃圾回收器就不會回收它,如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存, 軟引用可以加速JVM對垃圾內存的回收速度,可以維護系統的運行安全,防止內存溢出(OutOfMemory)等問題的產生。

3.弱引用(WeakReference)

如果一個對象只具有弱引用,那就類似于可有可物的生活用品。弱引用與軟引用的區別在于:只具有弱引用的對象擁有更短暫的生命周期。在垃圾回收器線程掃描它 所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由于垃圾回收器是一個優先級很低的線程, 因此不一定會很快發現那些只具有弱引用的對象.

4.虛引用(PhantomReference)

虛引用就是GC分分鐘會回收的引用 。虛引用并不會決定對象的生命周期;如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時候都可能被垃圾回收。

 

內存泄漏的幾種情況:

1.單例模式造成的泄漏:

在activity生命周期中使用單例模式的時候 ,當Activity A生命周期結束,但靜態類里面卻還存在activity的引用(mContext),這樣Activity就會占用的內存就一直不能回收,而靜態類的對象也不會再被使用,從而導致內存泄漏;

2.集合造成的泄漏:

集合類如果僅僅有添加元素的方法,而沒有相應的刪除機制,導致內存被占用。如果這個集合類是全局性的變量 (比如類中的靜態屬性,全局性的 map 等即有靜態引用或 final 一直指向它),那么沒有相應的刪除機制,很可能導致集合所占用的內存只增不減。比如我們都喜歡通過 HashMap 做一些緩存之類的事,這種情況就很容易導致泄漏問題。

3.匿名內部類/非靜態內部類導致內存泄漏:

匿名內部類/非靜態內部類和異步線程,默認都會持有外界的引用,如果前者突然因為某種原因要finish,或者activity突然掛掉 ,  但是系統判斷還有對象持有,那么就會造成內存泄漏。

4.線程造成的內存泄漏:

當我們在使用線程的時候,一般都使用匿名內部類,而匿名內部類會對外部類持有默認的引用,當Acticity關閉之后如果現成中的任務還沒有執行完畢,就會導致Activity不能正常回收,造成內存泄漏。

5.資源未關閉造成的內存泄漏:

對于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源的代碼,應該在Activity銷毀時及時關閉或者注銷,否則這些資源將不會被回收,造成內存泄漏

6.handler泄漏:

對于handler泄漏其實是由于消息隊列持有對handler的引用,而handler又持有activity的隱式引用,這個引用會保持到消息得到處理,而導致activity無法被垃圾回收器進行回收,而導致內存泄漏  ,使用static+WeakReference可以解決內存泄漏問題,不過不寫也無所謂 , 不加static的默認會在handler構造函數加上activity這個參數,只要handler沒有被回收,就會泄露。加static目的是為了防止泄露,為什么會泄露,就是因為沒回收,沒回收是因為還引用著。只有postDelayed的時候才會有泄露問題,因為delayed的時候activity的引用還保持著,所以只要delayed完了就能回收了,大多數情況下根本不必用加static。

內存檢測工具:

1.Android Studio有一個叫做Android Monitor的內置工具

2.Android studio自帶的功能

檢測過程中電腦會比較卡 , 不實用。

3.第三方檢測工具LeakCanary:

親測很實用 , 缺點就是檢測到有泄漏的時候會延遲幾秒才能推送到,而且會卡一下;

使用步驟  1.添加依賴:debugCompile'com.squareup.leakcanary:leakcanary-android:1.5'

releaseCompile'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

testCompile'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

2.在Application中進行配置:

3.在AndroidManifest.xml里面配置:

4.使用第三方檢測工具FindBugs:

在Android studio下載插件,下載后重啟一下Android studio, 然后會看到紅色的圖標:

點擊運行第五個按鈕:

插件運行幾分鐘后會出現以下結果:

 

來自:http://www.jianshu.com/p/6cf427ab0085

 

 本文由用戶 ojop5012 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!