Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android內存洩漏終極解決篇(上)

Android內存洩漏終極解決篇(上)

編輯:關於Android編程

一、概述
在Android的開發中,經常聽到“內存洩漏”這個詞。“內存洩漏”就是一個對象已經不需要再使用了,但是因為其它的對象持有該對象的引用,導致它的內存不能被回收。“內存洩漏”的慢慢積累,最終會導致OOM的發生,千裡之堤,毀於蟻穴。所以在寫代碼的過程中,應該要注意規避會導致“內存洩漏”的代碼寫法,提高軟件的健壯性。
本文將從發現問題、解決問題、總結問題的三個角度出發,循序漸進,徹底解決“內存洩漏”的問題。

二、內存洩漏的檢查工具Heap

工欲善其事必先利其器,要檢測“內存洩漏”的發生,需要借助DDMS中的Heap工具及MAT工具,Heap工具用於大致分析是否存在“內存洩漏”,而MAT工具則用於分析“內存洩漏”發生在哪裡。

Heap工具的使用介紹

這裡寫圖片描述

具體操作

  • 1.在Devices設備列表中,找到你所在的設備,點擊你想要監控的進程。
  • 2.點擊“Update Heap”按鈕更新堆內存的情況。
  • 3.點擊“Heap”視圖,查看內存的情況。
  • 4.每次在Activity的退出和進入的時候點擊“Cause GC”,手動調用GC釋放應用的內存。
  • 5.觀察data oject那一行,每一次點擊“Casue GC”的時候,觀察Total Size的值,如果該值不斷增加,則說明該應用程序存在“內存洩漏”。

我們先模擬一下內存洩漏,然後通過Heap工具來判斷一下是否存在內存洩漏。
上一段存在內存洩漏的代碼:

public class LeakAty extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.aty_leak);
  testLeak();

 }

 /**
  * 測試內存洩漏的代碼
  */
 private void testLeak() {
  new Thread(new Runnable() {

   @Override
   public void run() {
    while (true) {
     try {
      Thread.sleep(1000);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
   }
  }).start();
 }

上述的代碼存在內存洩漏,new Runnable(){}是一個非靜態的匿名內部類,所以它會強引用創建它的外圍對象LeakAty,我們來測試一下內存洩漏的過程,開啟手機的方向旋轉功能,不斷地旋轉手機,讓LeakAty不斷地創建新的實例。理論上如果不存在上述洩漏的代碼,之前的Activity會在onDestory之後被回收內存。而一旦存在上述洩漏的代碼,新創建的Ruannale實例會一直處於運行狀態,它不會被回收,而它強引用的LeakAty當然也不會被回收,所以在屏幕不斷旋轉,之前創建的LeakAty就不會被釋放,會導致旋轉n次,內存中就存在n+1個的LeakAty實例。
Heap工具第一次按下Cause GC按鈕的截圖:

這裡寫圖片描述 

上圖的data object的Total Size的大小為1.031M。經過多次的旋轉屏幕之後,我們再看一下截圖

這裡寫圖片描述 

Total Size變成了2.059M,從1.031M到2.059M,每次調用GC的過程中data object的總大小沒有回落,所以可以證實上面的代碼確實是存在內存洩漏的問題,那麼洩漏發生在哪裡?答案可以通過MAT工具來分析得到。

三、內存洩漏的分析工具MAT

要通過MAT分析,需要提供一個.hprof文件。我們可以通過”Dump HPROF file”按鈕轉存當前的堆內存信息。我們將其保存為1.hprof。

這裡寫圖片描述

導出的1.hprof的格式需要通過..\sdk\tools\目錄下的hprof-conv.exe工具進行轉換才能被MAT成功導入,我們將其轉換成out1.hprof
這裡寫圖片描述

將out1.hprof導入到MAT工具中,File->Open Heap Dump…

這裡寫圖片描述

點擊左邊的標簽Overview,Actions->Histogram

這裡寫圖片描述

在Histogram界面中,因為我們想要知道Activity是否洩漏了,所以輸入關鍵詞Activity,然後按下回車鍵。

這裡寫圖片描述

之後便可以得到Activity的相關的搜索結果,下圖的搜索結果中Activity的實例有7個。點擊選中下圖標紅色框框的地方,右鍵->Merge Shortest Paths to GC Roots->exclude all phantom/weak/soft etc. references。排除虛引用、弱引用、軟引用的實例,剩下的都是強引用實例。

這裡寫圖片描述

從過濾出來的強引用的列表中,我們可以看到這七個實例都是被Thread所引用了。所以證實上面的代碼確實存在內存洩漏。

這裡寫圖片描述

四、本文總結

內存洩漏檢測可以使用Heap工具,內存分析可以使用MAT工具。本文的案例中提到了一種內存洩漏的情況,就是非靜態內部類的對象會強引用其外圍對象,一旦這個非靜態內部類的實例沒有釋放,它的外圍對象也不會釋放,所以就會造成內存洩漏。下篇將具體探討一下,在Android的開發過程中,哪些寫法容易造成內存洩漏,該如何解決?請閱讀Android內存洩漏終極解決篇(下)。

以上就是本文的全部內容,希望大家喜歡。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved