Android內存泄漏分析

Android內存泄漏分析

本文轉載自:http://www.apkbus.com/home.php?mod=space&uid=705730&do=blog&id=61605

Android中的內存分爲:

  1. native進程:採用C/C++實現,不包含dalvik實例的進程。
  2. java進程:Android中運行於dalvik虛擬機之上的進程。每一個java進程都是存在於一個native進程中。

內存空間是一定的,所以在對象無用時就要回收一些對象來留出空間。當Java Garbage Collection開始運行時,它會從他了解還存活的對象作爲內存遍歷的根節點(GC Root),遍歷heap內存空間,沒有直接或間接引用到GC Root的對象便會被回收。

而Android內存泄漏便是指進程中的對象,雖然沒有使用價值了,但它仍然有直接或間接的引用到GC Root,那麼該對象便不會被GC回收,導致內存持續被佔用,使可用內存變小。

常見的內存泄漏

  1. 查詢數據庫沒有關閉Cursor。
  2. 使用BaseAdapter作爲適配器時沒有複用convertView。可以參考ListView與BaseAdapter優化.
  3. bitmap沒有回收,可以參考Bitmap相關:管理Bitmap內存.
  4. 註冊對象後沒有反註冊,比如Broadcast Receiver等。
  5. handler問題,如果handler是非靜態的,會導致Activity或者Service不被回收,所以應當註冊爲靜態內部類,同時在onDestroy時停止線程:mThread.getLooper().quit();
  6. Activity被靜態引用,特別是緩存bitmap時,解決方法可以考慮使用Application的context代替Activity的context。
  7. View在callback中被引用,可能回調還沒有結束,但是view處於引用狀態,無法回收

    public void leak(final View view) {
        api.callback(new callBack() {
            onCallBack() {
                ...
            }
        )
    }
    
  8. WebView的泄露問題:在魅族上面發現webView打開再關閉就會內存泄露..目前使用的解決方法是在webview外面嵌套一層layout作爲container.在Activity的onDestroy中調用container.removeAllViews()方法.
  9. Dialog導致Window泄露,如果需要在dialog依附的Activity銷燬前沒有調用dialog.dismiss().會導致Activity泄露

檢測內存泄露的方法

  1. Android Studio 自帶的 Memory Monitor,手動觸發GC可以看得比較直觀,但是dump出來的文件需要處理才能用MAT打開,利用 sdk/platforms-tool/ 下的 hprof-conv 文件,命令爲:

    /hprof-conv source output
    
  2. MAT這篇文章分析得比較透徹

  3. Leakcanary,檢測一些容易忽略的內存泄露很好用.
  4. adb shell dumpsys meminfo [包名]可以看到內存使用情況.

一些值得注意的地方

  1. 理論上來說,當你退出一個 Activity 後,強制GC一次,內存值應該回到跟進入 Activity 差不多的狀態,否則就有可能是內存泄露了.但是有可能是圖片加載庫中對新 Activity 中加載的圖片做了內存緩存,然而這部分內存 GC 可能暫時不會回收.

    比如在應用中我使用了 Fresco 去加載本地圖庫中的圖片, Fresco 對這些圖片做了內存緩存,然而這部分的圖片其實是不需要在內存中緩存的.

推薦:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章