Android應用性能之檢測內存泄漏

原文地址:

http://blogs.360.cn/blog/%E6%B5%85%E8%B0%88android%E5%BA%94%E7%94%A8%E6%80%A7%E8%83%BD%E4%B9%8B%E5%86%85%E5%AD%98/


如何測試一個APP的內存佔用情況?一個APP佔用的內存分哪些部分?如何檢查一個APP是否存在內存泄漏? 


一、Android內存介紹:

在java開發過程中,是通過new來爲對象分配內存的,而內存的釋放是由垃圾收集器(GC)來回收的,在開發的過程中,不需要顯式的去管理內存,java虛擬機會自動幫我們回收內存。但是這樣有可能在不知不覺中就會浪費了很多內存,最終導致java虛擬機花費很多時間去進行垃圾回收,更嚴重的是造成JVM的OOM。


二、APP佔用的內存分哪些

Android系統中的內存和linux系統一樣,存在着大量的共享內存。每個APP佔內存會有私有和公共的兩部分:ShareDirty、PrivateDirty。Pss是考慮共享內存的內核計算尺度 — 基本上一個進程的每個內存頁面被按一個比率縮減,這個比率和同樣使用該頁面的其他進程的數量有關。理論上你可以累計所有進程的Pss佔用量來檢查所有進程的內存佔用量,也可以比較進程的Pss來大致發現進程各自的權重。PrivateDirty,它基本上是進程內不能被分頁到磁盤的內存,也不和其他進程共享。

手機中系統設置裏有可以查看正在運行的應用程序所佔的內存,此處顯示的內存爲該進程所佔用的Total Pss。所以我們只需要查看Total Pss的值就可以知道該應用運行時所佔的內存的大小。

 

三、如何查看一個APP佔用的內存

查看內存大致上有三種方法:

1. 通過系統設置查看

在系統設置中->應用->正在運行->APP

優點:操作簡單

缺點:數值不準確,無法實時查看數值變化

2. 通過命令行查看

adb shell dumpsys meminfo yourpakagename

結果如下圖所示

1

其中Pss對應的TOTAL值爲內存所實際佔用的值

優點:簡單方便,數據全面精確

缺點:無法實時查看內存佔用

3. 通過系統API查看

首先通過activitymanager獲得正在運行的程序列表,找到所要獲取的程序的pid。

activitymanager.getRunningAppProcesses()

再通過memoryinfo[0].getTotalPss();方法獲得實際內存佔用

Memoryinfo中還包括getTotalPrivateDirty和getTotalSharedDirty方法

優點:可拓展性高,可以通過程序實時查看內存的佔用;數據全面精確

缺點:需要具有開發能力,入手較爲困難

所以我們現在在測試內存的時候,是使用了內部自己研發的一款APP來監測內存的,這個APP目前可以實現實時監測並記錄數據結果,可以提供給開發者和測試者分析內存的數據支持。目前仍然屬於內測階段,以後有機會可以提供給大家使用。

 

四、內存泄漏

何爲內存泄漏?內存泄漏也稱作“存儲滲漏”,用動態存儲分配函數動態開闢的空間,在使用完畢後未釋放,結果導致一直佔據該內存單元,直到程序結束。

內存泄漏的實例:

btn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View arg0) {

for (int i = 0; i < 100; i++) {

ImageView img = new ImageView(MainActivity.this);

img.setImageResource(R.drawable.ic_launcher);

test.add(img);

}

}

});

其中test爲靜態的List<ImageView>。

這樣,如果一直點擊btn就會出現內存泄漏的情形。

 

我們如何去監測內存泄漏呢?

例:

以上面內存泄漏的例子爲測試Activity,當點擊按鈕後,會向一個靜態數組中添加圖片,這樣就形成了一個內存泄漏的場景。

進入測試Activity,在點擊按鈕前先記錄當前APP所佔用的內存,然後點擊按鈕。等待操作執行完成後,進行一次GC,再查看APP所佔用的內存。

返回後APP所佔用的內存沒有明顯的回落,表明在代碼中可能存在內存泄漏的情況發生。

 

即:在執行某種操作後進行一次GC,內存沒有明顯的回落。此時即可以斷定代碼中可能存在內存泄漏。

 

檢測方法:

  1. 通過上文所用的三種方法去查看內存的使用情況
  2. 使用DDMS中的Heap:

1)      打開DDMS並打開Devices視圖和Heap視圖

2)      點擊選擇要監控的進程

3)      選中Devices視圖界面上的”update heap” 圖標

4)      點擊Heap視圖中的”Cause GC” 按鈕(相當於進行了一次GC的操作)

一般我們會觀察Data Object的Total值,正常情況下在每次GC後,這個值都會有明顯的回落並會穩定在一個範圍之內,說明代碼中沒有未被釋放的內存;若這個值在每次GC後沒有出現明顯的回落,則說明代碼中可能存在沒有被釋放的內存。

 

總述:內存不僅是性能測試時需要關注的,作爲優秀的開發工程師更應該關注自己的代碼內存佔用的情況,這樣可以儘量避免OoM的情況發生。要知道手機分配給每個進程的內存並不多,當系統內存不夠的時候會kill掉一些佔內存高的進程,所以爲了不被系統kill掉我們要儘可能的合理使用內存避免內存泄漏的情況發生。

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