Android記憶體泄露常見問題總結

來源:互聯網
上載者:User

 在介紹記憶體流失之前很有必要提及一下Android系統的記憶體回收機制。Java GC(Garbage Collection,垃圾收集,記憶體回收)機制,是Java與C++/C的主要區別之一,作為Java開發人員,不需要專門編寫記憶體回收和垃圾清理代碼,對記憶體泄露和溢出的問題,也不需要像C程式員那樣戰戰兢兢。這是因為在Java虛擬機器中,存在自動記憶體管理和垃圾清掃機制。概括地說,該機制對虛擬機器中的記憶體進行標記,並確定哪些記憶體需要回收,根據一定的回收策略,自動的回收記憶體,永不停息(Nerver Stop)的保證虛擬機器中的記憶體空間,防止出現記憶體泄露和溢出問題。Android系統的記憶體回收是基於可達性分析演算法(根搜尋演算法)的。從GC Roots(每種具體實現對GC Roots有不同的定義)作為起點,向下搜尋它們引用的對象,可以產生一棵引用樹,樹的節點視為可達對象,反之視為不可達,不可達對象會被回收。
    舉個例子,我們在開發中經常使用單例模式,單例的靜態特性導致其生命週期同應用一樣長。有時建立單例時如果我們需要Context對象,如果傳入的是Application的Context那麼不會有問題。如果傳入的是Activity的Context對象,那麼當Activity生命週期結束時,該Activity的引用依然被單例持有,所以不會被回收,而單例的生命週期又是跟應用一樣長,這個情況就叫做記憶體泄露(Memory Leak)。它指的是當你不再需要某個執行個體後,但是這個對象卻仍然被引用,防止被記憶體回收(Prevent from being bargage collected)。
public class Util {
    private Context mContext;
    private static Util sInstance;
    private Util(Context context) {
        this.mContext = context;
    }
    public static Util getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new Util(context);
        }
        return sInstance;
    }
}
本傑明 富蘭克林曾說:A small leak will sink a great ship(小漏不補沉大船)。基於Android系統的裝置一般來說記憶體就不大,特別是早期的Android裝置,記憶體流失是很致命的,記憶體流失積攢到一定程度會引發記憶體溢出(OOM),如果處理不當直接導致程式崩潰退出。
常見的記憶體流失
一般來說在開發中我們經常會犯下下面幾個錯誤,導致記憶體流失。這幾個都是前人踩坑總結出來的,非常有參考價值,至少我在排查解決記憶體流失的時候是這樣的。
一. 單例造成的記憶體流失

Android的單例模式非常受開發人員的喜愛,不過使用的不恰當的話也會造成記憶體流失。因為單例的靜態特性使得單例的生命週期和應用的生命週期一樣長,這就說明了如果一個對象已經不需要使用了,而單例對象還持有該對象的引用,那麼這個對象將不能被正常回收,這就導致了記憶體流失。例子見上面那段代碼。
二、非靜態內部類建立靜態執行個體造成的記憶體流失

有的時候我們可能會在啟動頻繁的Activity中,為了避免重複建立相同的資料資源,在Activity內部建立了一個非靜態內部類的單例,每次啟動Activity時都會使用該單例的資料,這樣雖然避免了資源的重複建立,不過這種寫法卻會造成記憶體流失,因為非靜態內部類預設會持有外部類的引用,而又使用了該非靜態內部類建立了一個靜態執行個體,該執行個體的生命週期和應用的一樣長,這就導致了該靜態執行個體一直會持有該Activity的引用,導致Activity的記憶體資源不能正常回收。例子如下
public class MainActivity extends AppCompatActivity {

    private static TestResource mResource = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        if (mResource == null) {

            mResource = new TestResource();

        }

        //......

    }

    class TestResource {

        //......

    }

}
三、Handler造成的記憶體流失

Handler的使用造成的記憶體流失問題應該說最為常見了,平時在處理網路任務或者封裝一些請求回調等api都應該會藉助Handler來處理,我們經常在Activity裡面這樣定義一個私人的Handler對象並初始化,這種建立Handler的方式會造成記憶體流失,由於mHandler是Handler的非靜態匿名內部類的執行個體,所以它持有外部類Activity的引用,我們知道訊息佇列是在一個Looper線程中不斷輪詢處理訊息,那麼當這個Activity退出時訊息佇列中還有未處理的訊息或者正在處理訊息,而訊息佇列中的Message持有mHandler執行個體的引用,mHandler又持有Activity的引用,所以導致該Activity的記憶體資源無法及時回收,引發記憶體流失。
private Handler mHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {

        //.....

    }
};
四、資源未關閉造成的記憶體流失

對於使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或者登出,否則這些資源將不會被回收,造成記憶體流失。
檢測記憶體流失的常見工具
LeakCanary是Square開源了一個記憶體泄露自動探測神器 。對應的github倉庫地址:https://github.com/square/leakcanary  。使用非常簡單,在build.gradle中引入包依賴:
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'
在Application中的onCreate方法中增加初始化代碼:

if (LeakCanary.isInAnalyzerProcess(this)) {
    // This process is dedicated to LeakCanary for
    // heap analysis.
    // You should not init your app in this process.
    return;
}
LeakCanary.install(this);
整合後什麼都不用做,按照正常測試,當有記憶體流失發生後,應用會通過系統通知欄發出通知,點擊通知就可以進入查看記憶體流失的具體資訊。其實無論是MAT工具的記憶體分析,還是AndroidStudio中內建的分析工具亦或是LeakCanary,原理都是一樣的,都是dump java heap出來進行分析,找到泄漏的問題,只是LeakCanary幫我們把分析的工作做了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.