基於Android Studio的記憶體洩漏檢測與解決全攻略
自從Google在2013年釋出了Android Studio後,Android Studio憑藉著自己良好的記憶體最佳化,酷炫的UI主題,強大的自動補全提示以及Gradle的編譯支援正逐步取代Eclipse,成為主流的Android開發IDE。Android Studio在為我們提供了良好的編碼體驗的同時,也提供了許多對App效能分析的工具,讓開發者可以更方便分析App效能。Google在IO大會上一直告誡開發者不要無節制的使用手機記憶體,要注意一些不良的開發習慣會導致App的記憶體洩漏。雖然如今網上檢測App記憶體洩漏的文章汗牛充棟,但是要使用DDMS和MAT,不僅使用步驟複雜繁瑣,而且要手動排查記憶體洩漏的位置,操作起來多有不便。其實Android Studio已經開始支援自動進行記憶體洩漏檢查了,本文就帶著大家一探其中的奧妙吧。
什麼是記憶體洩漏
Android虛擬機器的垃圾回收採用的是根搜尋演算法。GC會從根節點(GC Roots)開始對heap進行遍歷。到最後,部分沒有直接或者間接引用到GC Roots的就是需要回收的垃圾,會被GC回收掉。而記憶體洩漏出現的原因就是存在了無效的引用,導致本來需要被GC的物件沒有被回收掉。
舉個例子
private static Leak mLeak; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); mLeak = new Leak(); } class Leak { }
mLeak是儲存在靜態區的靜態變數,而Leak是內部類,其持有外部類Activity的引用。這樣就導致Activity需要被銷燬時,由於被mLeak所持有,所以系統不會對其進行GC,這樣就造成了記憶體洩漏。
再舉一個最常犯的栗子
public class Singleton { private static Singleton instance; private Context mContext; private Singleton(Context context){ this.mContext = context; } public static Singleton getInstance(Context context){ if (instance == null){ synchronized (Singleton.class){ if (instance == null){ instance = new Singleton(context); } } } return instance; } }
如果我們在在呼叫Singleton的getInstance()方法時傳入了Activity。那麼當instance沒有釋放時,這個Activity會一直存在。因此造成記憶體洩露。
解決方法可以將new Singleton(context)改為new Singleton(context.getApplicationContext())即可,這樣便和傳入的Activity沒關係了。
記憶體洩漏的檢測
開啟Android Studio,編譯程式碼,在模擬器或者真機上執行App,然後點選,在Android Monitor下點選Monitor對應的Tab,進入如下介面
在Memory一欄中,可以觀察不同時間App記憶體的動態使用情況,點選可以手動觸發GC,點選可以進入HPROF Viewer介面,檢視Java的Heap,如下圖
Reference Tree代表指向該例項的引用,可以從這裡面檢視記憶體洩漏的原因,Shallow Size指的是該物件本身佔用記憶體的大小,Retained Size代表該物件被釋放後,垃圾回收器能回收的記憶體總和。
下面我們以掌上道聚城客戶端為例,來一探記憶體洩漏檢測的方法。
開啟Android Studio,編譯程式碼,執行掌上道聚城,然後開始盡情的耍我們的App啦,然後就從Memory Monitor裡面觀察App的記憶體使用曲線,突然發現,納尼!!!怎麼記憶體使用越來越大了,這就很有可能是發生記憶體洩漏了,然後點選手動進行GC,再點選觀看JavaHeap,點選Analyzer Task,Android Monitor就可以為我們自動分析洩漏的Activity啦,分析出來如下圖所示
在Reference Tree裡面,我們直接就可以看到持有該Activity的單例物件,直接定位到該單例中的程式碼,發現程式碼中出現了
public static VideoTagHelper getInstance(Context context) { if (tagHelper == null) { tagHelper = new VideoTagHelper(); } tagHelper.context = context; return tagHelper; }
和剛剛舉得栗子裡出現的錯誤一模一樣啊,這段程式碼是誰寫的,拖出去······
我們修復了檢查出的記憶體洩漏的問題,並將修復前和修復後的程式碼在相同的模擬器上執行並進行相同的操作,檢視他們使用記憶體的情況,如下圖所示
有記憶體洩漏的情況,佔用記憶體約為43M
修復了記憶體洩漏問題,佔用記憶體為36M
在修復了記憶體洩漏問題後,記憶體使用下降了16.3%!!!
掌握了Android Monitor的使用方法後,媽媽再也不擔心我寫的App會出現記憶體洩漏啦!!!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3549/viewspace-2814648/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android記憶體洩漏檢測與修復技巧Android記憶體
- Android 輕鬆解決記憶體洩漏Android記憶體
- iOS檢測記憶體洩漏iOS記憶體
- Android記憶體洩漏Android記憶體
- Android 記憶體洩漏Android記憶體
- Java記憶體洩漏解決之道Java記憶體
- Android 記憶體洩漏檢測工具 LeakCanary(Kotlin版)的實現原理Android記憶體Kotlin
- 如何在 Linux 下檢測記憶體洩漏Linux記憶體
- Android中的記憶體洩漏模式Android記憶體模式
- Android中常見的記憶體洩漏Android記憶體
- 解決Android記憶體洩漏;輕鬆降低100MAndroid記憶體
- Android記憶體洩漏場景Android記憶體
- Handler記憶體洩漏分析及解決記憶體
- 解決Instruments檢測記憶體洩漏時真機無法定位的問題記憶體
- 解決記憶體洩漏(1)-ApacheKylin InternalThreadLocalMap洩漏問題分析記憶體Apachethread
- Android Native 記憶體洩漏系統化解決方案Android記憶體
- Android技術分享| Android 中部分記憶體洩漏示例及解決方案Android記憶體
- Android備忘錄《記憶體洩漏》Android記憶體
- 初步探究Android記憶體洩漏(1)Android記憶體
- 記憶體的分配與釋放,記憶體洩漏記憶體
- Handler記憶體洩漏原因及解決方案記憶體
- 使用VLD進行記憶體洩漏檢測(release + debug)記憶體
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- 如何檢查Javascript中的記憶體洩漏JavaScript記憶體
- Handler的使用、記憶體洩漏和解決記憶體
- Android Handler機制之記憶體洩漏Android記憶體
- Android常見記憶體洩漏總結Android記憶體
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- C++--問題27--如何檢測記憶體洩漏C++記憶體
- 記憶體洩漏的原因記憶體
- [Java基礎]記憶體洩漏和記憶體溢位Java記憶體溢位
- 深入瞭解 JavaScript 記憶體洩漏JavaScript記憶體
- js記憶體洩漏JS記憶體
- jvm 記憶體洩漏JVM記憶體
- Java記憶體洩漏Java記憶體
- 關於PHP記憶體洩漏的問題PHP記憶體
- Android之記憶體洩漏除錯學習與總結Android記憶體除錯
- 手把手教你解決 Flutter engine 記憶體洩漏Flutter記憶體