1. 程式人生 > >Android應用記憶體洩露分析、改善經驗總結

Android應用記憶體洩露分析、改善經驗總結

前言

  通過這幾天對好幾個應用的記憶體洩露檢測和改善,效果明顯:

  • 完全退出應用時,手動觸發GC,從原來佔有記憶體100多M降到低於20M;

  • 手動觸發GC後,通過adb shell dumpsys meminfo packagename -d檢視Activity和View的數量也趨近於0了(沒有做到歸零是因為SDK中存在記憶體洩露,需要中間層去處理);

  • 發現一個MTK Webview的記憶體洩露(org.chromium.android_webview.AwPasswordHandler.java中private static AwPasswordHandler sInstance = null導致的記憶體洩露)。

  從結果來看我分析和改善記憶體洩露的方法是對的,這個過程並不複雜,所以可以梳理總結出來作為分享。

原則

  對於效能問題,分析和改善有必要遵循以下原則:

  • 一切看資料說話,不能跟著感覺走,感覺哪有問題就去改,很有可能會適得其反;

  • 效能優化是一個持續的過程,需要不斷地改善,不要想著一氣呵成;

  • 對於效能問題,不一定必須要改善,受限於架構或者其它原因某些問題可能會很難改善,必須要先保證能用,再才考慮好用。

  • 改善後一定要驗證,任何一個地方的改動都需要驗證,避免因為改善效能問題導致其它的問題。

步驟

  下面是我在針對記憶體洩露這個效能問題上的解決步驟:

優先處理常見的記憶體洩露問題

  首先解決常見的記憶體洩露問題,這個過程可以藉助Android Studio的Analyze-Inspect Code對程式碼做靜態分析,常見的記憶體洩露問題有:

  • 非靜態內部類導致的記憶體洩露,比如Handler,解決方法是將內部類寫成靜態內部類,在靜態內部類中使用軟引用/弱引用持有外部類的例項,eg:

          static class ExerciseHandler extends Handler{
              private SoftReference<ExerciseActivity> exerciseActivitySoftReference = null;
    
              public ExerciseHandler(ExerciseActivity exerciseActivity){
                  exerciseActivitySoftReference = new
    SoftReference<ExerciseActivity>(exerciseActivity); } @Override public void handleMessage(Message msg) { ExerciseActivity exerciseActivity = exerciseActivitySoftReference.get(); if(null != exerciseActivity){ super.handleMessage(msg); switch (msg.what) { case MSG_XX: exerciseActivity.***; breakdefault: break; } } } }
  • IO操作後,沒有關閉檔案導致的記憶體洩露,比如Cursor、FileInputStream、FileOutputStream使用完後沒有關閉,這種問題在Android Studio 2.0中能夠通過靜態程式碼分析檢查出來,直接改善就可以了;

  • 自定義View中使用TypedArray後,沒有recycle,這種問題也可以在Android Studio 2.0中能夠通過靜態程式碼分析檢查出來,直接改善就可以了;

  • 某些地方使用了四大元件的context,在離開這些元件後仍然持有其context導致的記憶體洩露,這種問題屬於共識,在編寫程式碼的過程中就應該按照規則來,使用Application的Context就可以解決這類記憶體洩露的問題了,至於什麼情況下應該使用四大元件的Context,什麼時候應該使用Application的context可以參見下表:


    application使用場景

  備註:大家注意看到有一些NO上添加了一些數字,其實這些從能力上來說是YES,但是為什麼說是NO呢?下面一個一個解釋:

1、數字1:啟動Activity在這些類中是可以的,但是需要建立一個新的task,一般情況不推薦;

2、數字2:在這些類中去layout inflate是合法的,但是會使用系統預設的主題樣式,如果你自定義了某些樣式可能不會被使用;

3、數字3:在Receiver為null時允許,在4.2或以上的版本中,用於獲取黏性廣播的當前值。(可以無視);

4、ContentProvider、BroadcastReceiver之所以在上述表格中,是因為在其內部方法中都有一個context用於使用。
  • 還有一種不屬於記憶體洩露,但在分析記憶體洩露的問題時應該一併解決:同一個APP,將圖片放在不同的drawable資料夾下,在相同的裝置上佔用的記憶體情況不一樣,具體可以參見:關於Android中圖片大小、記憶體佔用與drawable資料夾關係的研究與分析。解決這個問題遵循以下原則就可以了:

    1、UI只提供一套高解析度的圖,圖片建議放在drawable-xxhdpi資料夾下(放在xxxhdpi或者更高解析度的資料夾下沒有必要,權衡利弊,照顧主流裝置即可),這樣在低解析度裝置中圖片的大小隻是壓縮,不會存在記憶體增大的情況;

    2、涉及到桌面外掛或者不需要縮放的圖片,放在drawable-nodpi資料夾下,這個資料夾下的圖片在任何裝置上都是不會縮放的。

通過工具檢查程式執行後的記憶體洩露

  通過上面的步驟,應用中的大部分記憶體洩露問題都能夠得到解決,還有一些記憶體洩露,需要執行程式,分析執行後的記憶體快照來解決,比如註冊之後沒有反註冊、類中的靜態成員變數導致的記憶體洩露、SDK中的記憶體洩露等。解決這類問題可以分兩步進行:

  • 通過記憶體洩露檢測工具先定位是哪有問題,記憶體洩露的檢測有兩種比較便捷的方式:

    1、一種是使用開源專案Leakcanary,需要新增到程式碼中,執行後生成分析結果;

    2、另一種方式是使用adb shell dumpsys meminfo packagename -d命令,在進入一個介面之前檢視一遍Activity和View的數量,在退出這個介面之後再檢視一遍Activity和View的數量,對比進入前和進入後Activity和View數量的變化情況,如果有差異,則說明存在記憶體洩露(在使用命令檢視Activity和View的數量之前,記得手動觸發GC)。


    備註:在Android Studio中,可以通過如下方式獲取當前選中程序的記憶體資訊:


  • 然後通過MAT取程式執行時的記憶體快照做詳細分析,對於MAT的使用,網上有很多優質的文章,比如:Android 效能優化之使用MAT分析記憶體洩露問題,在使用MAT前,有必要知道這幾點:

    1、 不要指望MAT明確告訴你哪裡存在記憶體洩露,這需要你根據上一步驟首先定位到可能存在記憶體洩露的類,然後藉助MAT確認是否真的存在記憶體洩露,具體哪個地方存在記憶體洩露;

    2、藉助Retained Size分析某一個類及與之相關的例項所消耗的記憶體,如果這個類的Retained Size比較大,優先分析;

    3、檢查某個類是否存在記憶體洩露時,排除其軟/弱/虛引用,右鍵某個類→Merge Shortest Paths to GC Roots→exclude all phantom/weak/soft etc.references。

驗證改善效果

  根據個人經驗,我一般是這樣驗證改善效果的,執行程式,各個功能跑一遍,確保沒有改出問題,完全退出程式,手動觸發GC,然後通過adb shell dumpsys meminfo packagename -d檢視Activivites和Views的數量是否趨近於0;如果不是0,通過Leakcanary檢查可能存在記憶體洩露的地方,繼續通過MAT分析,周而復始,改善到自己滿意為止。

推薦閱讀

相關推薦

Android應用記憶體洩露分析改善經驗總結

前言   通過這幾天對好幾個應用的記憶體洩露檢測和改善,效果明顯: 完全退出應用時,手動觸發GC,從原來佔有記憶體100多M降到低於20M; 手動觸發GC後,通過adb shell dumpsys meminfo packagename -d檢視Activity和View的數量也趨近於0了(沒有做到歸零

Android應用記憶體洩露分析以及優化方案

文章轉載http://blog.csdn.net/Soiol/article/details/52486871        本篇部落格是介紹Android記憶體優化方面的知識,在讀本篇部落格之前需要你熟練掌握Java 基礎知識(例如,靜態變數的生命週期,匿名內部類的使用,匿名物件等),並且具有一定的Andr

Android studio記憶體洩露分析工具使用

什麼是記憶體洩漏 Android虛擬機器的垃圾回收採用的是根搜尋演算法。GC會從根節點(GC Roots)開始對heap進行遍歷。到最後,部分沒有直接或者間接引用到GC Roots的就是需要回收的垃圾,會被GC回收掉。而記憶體洩漏出現的原因就是存在了無

android開發記憶體洩露分析

記憶體洩露分析: 在android開發的專案中,記憶體洩露是影響產品穩定性的最大誘因,目前總結到的記憶體洩露的2大源頭如下: 1.Bitmap記憶體未被釋放 Bitmap記憶體洩露是所有原因中最嚴重的一個,因為Bitmap物件引用的記憶體分JAVA層和C層,而GC機制在一

VUE SSR記憶體洩露解決過程和經驗總結

先上JS記憶體洩露的幾個常見原因 1.全域性變數引起的記憶體洩漏。2.閉包引起的記憶體洩漏.3.dom清空或刪除時,事件未清除導致的記憶體洩漏 node方面的記憶體洩露也基本差不多, 處理過程瞭解到的VUE方面的記憶體洩露的原因 1.計算屬性無返回情況下,導致的異常 vue高版本已修復.2.引用第三方

Android記憶體洩露記憶體溢位記憶體抖動分析

記憶體 JAVA是在JVM所虛擬出的記憶體環境中執行的,記憶體分為三個區:堆、棧和方法區。 棧(stack):是簡單的資料結構,程式執行時系統自動分配,使用完畢後自動釋放。優點:速度快。 堆(heap):用於存放由new建立的物件和陣列。在堆中分配的記憶體,一方面由jav

Android記憶體洩露分析

一,記憶體洩露 記憶體洩露:一個不在被使用的物件被另一個存活著的物件引用,在這種情況下垃圾回收器會跳過他,因為這種引用關係足以讓該物件駐留在記憶體中,記憶體洩露是在組織垃圾回收器為未來的記憶體分配提供空間,這些洩露的物件一直佔據著記憶體,導致我們的堆記憶體空間變得更小。也加劇了垃圾回

轉載:Android 記憶體洩露分析實戰演練

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://mp.csdn.net/postedit/82736058 轉載自任玉剛微信推文,非常全面所以記錄下來 1. 記憶體洩露簡介 記憶體洩露,即Memory Leak,指程式中不再使用到的物件因某種原因從而無法被GC正常回

測試Android應用記憶體CPU以及耗電量

這些天在測試Android應用在執行時記憶體、CPU佔用以及耗電量時,找到了兩個還可以,記錄下:一個時Emmagee,這是網易開發的;一個是Trepn,是高通公司開發的。 Trepn下載事先註冊,要麼在Google Play下載。另外不是所有的手機

應用記憶體洩露起因與解決方案分析

java gc機制 java記憶體管理與c/c++不同,java使用garbage collection機制,由虛擬機器管理記憶體。在大部分虛擬機器(包括android的ART)中,都採用了“可達性”分析演算法來進行記憶體管理。 原理是:選取某幾個root節

分析並優化 Android 應用記憶體佔用

視訊觀看筆記,如需轉載,請註明出處 演講人介紹 Rechard Uhler,Android Runtime 開發工程師。為便於寫作,筆者將以第一人稱視角對視訊內容進行概述。 視訊地址 1. 前言 想要進行記憶體優化,就必須對 Android 記憶體管理機制有比較深入的瞭解,這樣

Android記憶體洩露分析工具—Android Monitor

記憶體洩露大家應該不會陌生了,通常是因為該被釋放的物件被佔用,不能及時對其釋放,導致GC無法正常回收。我們可以使用一些工具來監控和分析導致記憶體洩露的位置和原因。用Eclipse的同志應該都知道MAT(Memory Analysis Tools),Android

Android記憶體洩露分析簡要思路

工作中遇到挺多需要分析記憶體洩露問題的情況,現在大致簡要寫下思路,等之後時間相對比較充裕再進行補充。 1.明白記憶體洩露的判斷依據? 個人總結為:持續增加,只增不減! 理解一下這8個字,配合幾個命令和工具來確定一下你的應用是否存在記憶體洩露問題,這是很關鍵的,如果一開始就判斷錯誤了

android 應用記憶體分析MAT結合LeakCanary的分析OOM異常

朋友們在開發應用過程中,可能會碰到OOM異常,通常造成的原理是物件沒有及時釋放,或者載入Bitmap過多過大導致的。 一、匯入LeakCanary 使用的方法也十分的簡單 在Gradle檔案中加入

Android Studio + MAT 給你看真實專案實戰的記憶體洩露分析

先貼出我要進行實戰的專案背景;專案已經出爐快半年時間了,現在要對它進行效能上的優化,這時候就要使用到 MAT 。然後隨便記錄一下我的分析歷程。 首先要了解兩個概念:記憶體溢位和記憶體洩漏 記憶體溢位

應用記憶體洩露問題分析例項

記憶體洩露,這個應用開發中比較容易出現的問題,由於短時間內難以測出來一般都比較難以發現,只能靠開發者的警覺性來避免,長時間的Monkey測試就成為一個可行的手段。 Monkey測試能給出一個直觀的記憶體變化曲線和日誌,GC日誌在記憶體緊張時都會打印出測試程序的記憶體資訊。往

Android記憶體洩露分析之StrictMode

轉載請註明地址:http://blog.csdn.net/yincheng886337/article/details/50524709 StrictMode(嚴格模式)使用 StrictMode嚴

Android Native記憶體洩露檢測(針對Android7.0)

1. 需要合入一個 Patch 2. 執行指令 adb root adb shell setprop libc.debug.malloc.program cameraserver adb shell setprop libc.debug.malloc.options “backt

Android應用內展示wordexcelpdfppt等檔案

筆者最近兩個專案裡頭都有需要展示檔案的功能,於是做了一番調研,發現asce1885給出一份方案,不過都是關於pdf的展示:http://www.jianshu.com/p/1bf49af6584d,顯然不符合筆者的要求,筆者的專案裡需要展示的檔案格式並不單一,後來經過一番搜尋最後敲定使用

記一次尷尬的Java應用記憶體洩露排查

這星期被線上JVM記憶體佔用不斷增大的問題所困擾,自己提出了一些假設,然後去實施驗證都一一失敗了,有一些經驗和教訓在這裡分享下. 之所以是尷尬,是最後因為偶爾出現修復了另一個問題導致記憶體不再上升,但這之間的關係還未明瞭,還需要繼續追蹤. 這裡講述一下這次排查的過程. 直接記憶體的錯誤判斷 伺服器的JVM配