离开当前屏幕的判断方法_Android App内存泄露测试方法总结
喜歡我的文章,歡迎關(guān)注微信公眾號「軟件測試藝術(shù)」,一起學習提高。
1、 內(nèi)存泄露
Android系統(tǒng)為每一個運行的程序都指定了一個最大運行內(nèi)存,超過這個值則會觸發(fā)OOM機制,反應(yīng)在界面就是閃退、 Crash現(xiàn)象,導致OOM發(fā)生的原因比如內(nèi)存泄露或者是代碼不考慮后果使用大量的資源,都有可能導致OOM出現(xiàn)的。OOM的臨界值可以通過adb shell getprop | findstr “heap”查看到:
2、 Android的GC機制
Android GC機制沿用了java的GC機制,當需要新內(nèi)存去分配對象的時候而剩余不夠的時候,會觸發(fā)GC,把無用的對象回收掉,其中一個重要的算法便是分代式算法,這個算法把虛擬機分為年輕代、老年代和持久代,對象先分配到年輕代,然后GC多次后還存活的將會移動到老年代,老年代就不會頻繁觸發(fā)GC機制,一般觸發(fā)頻繁的都是年輕代的對象。
3、 為什么會內(nèi)存泄露
上面我們知道了GC機制,那么如果GC過后程序還是沒有內(nèi)存,那么會發(fā)生OOM,導致GC后還是沒有足夠內(nèi)存分配新對象的主要原因就是內(nèi)存泄露了。首先要知道內(nèi)存泄露也就是GC不掉的根源是生命周期長的對象持有生命周期短的對象,導致無用的對象一直無法回收。以下是幾個典型的分類:
1)**靜態(tài)類相關(guān)的泄露:**static對象的生命周期伴隨著整個程序的生命周期,所以這塊要注意不要把一些對象引用添加到static對象里面去,會造成與之關(guān)聯(lián)的對象無法回收。
2)各種資源的釋放:包括cursor的關(guān)閉,IO流的關(guān)閉,bitmap的回收等,進行一些帶有緩存的資源一定要關(guān)閉或者釋放。
3)Handler的泄露:調(diào)用handler的delay的時候,會被認為對象是有用的,導致無法回收,還有handler開啟線程去下載東西沒有下載完成的時候,也會因為線程導致無法回收activity;或者使用handlerThread的時候,有延遲的方法,都會導致無法回收。其主要原因在于handler是持有activity的引用,主線程不是自帶一個Looper然后給handler用,導致有關(guān)聯(lián)關(guān)系。
4)各種注冊引用方法:比如一個常駐的后臺線程處理某些時間,把當前對象注冊,因為一直持有對象引用,導致這個activity一直保留,所以不用的時候需要反注冊。
5)把對象緩存進容器內(nèi)卻忘記remove掉:有時候為了加快頁面響應(yīng),結(jié)果緩存一些對象到容器內(nèi),結(jié)果越加越多,然后掛掉。
4、 系統(tǒng)級別的內(nèi)存管理
1)LMK機制和oom_adj的值
Android內(nèi)核有個專用的驅(qū)動low-memory-kill,當系統(tǒng)級別的內(nèi)存不夠的時候會根據(jù)oom_adj的值以及內(nèi)存分配狀況去kill掉某個進程,oom_adj可以在/proc/[pid]/oom_adj看到,并且這個值會隨著進程的狀態(tài)改變而改變,比如系統(tǒng)進程一般是-16,越大越容易被干掉。
2)5個進程的優(yōu)先級
前臺進程:當前運行的,基本不死 ;
可見進程:界面可以見到,比如被遮擋 ;
服務(wù)進程:進程帶后臺服務(wù)的,比如播放器 ;
后臺進程:點擊home鍵,但不退出,就是后臺進程了,有比較大幾率會被殺;
空進程:退出應(yīng)用程序,還在后臺保留這空進程,為的是加快啟動速率,最優(yōu)先。
5、 內(nèi)存抖動
內(nèi)存抖動是指內(nèi)存頻繁地分配和回收,而頻繁的GC會導致卡頓,嚴重時還會導致OOM(主要原因還是有因為大量小的對象頻繁創(chuàng)建,導致內(nèi)存碎片,從而當需要分配內(nèi)存時,雖然總體上還是有剩余內(nèi)存可分配,而由于這些內(nèi)存不連續(xù),導致無法分配,系統(tǒng)直接就返回OOM了)
6、 內(nèi)存名詞VSS、RSS、PSS、USS解釋
VSS - Virtual Set Size 虛擬耗用內(nèi)存(包含共享庫占用的內(nèi)存)
RSS - Resident Set Size 實際使用物理內(nèi)存(包含共享庫占用的內(nèi)存)
PSS - Proportional Set Size 實際使用的物理內(nèi)存(比例分配共享庫占用的內(nèi)存)
USS - Unique Set Size 進程獨自占用的物理內(nèi)存(不包含共享庫占用的內(nèi)存)
大小規(guī)律:
一般來說內(nèi)存占用大小有如下規(guī)律:VSS >= RSS >= PSS >= USS
7、 內(nèi)存值獲取方法
使用命令 adb shell dumpsys meminfo package_name 獲取內(nèi)存信息,如日歷的內(nèi)存信息如下:
PSS Total:進程各部分內(nèi)存的消耗,是所有進程PSS相加得到系統(tǒng)占用內(nèi)存的總和
Native Heap:Native代碼分配的內(nèi)存,虛擬機和Android框架分配內(nèi)存。關(guān)于什么是Native代碼,即非Java代碼分配的內(nèi)存
Dalvik Heap:Java對象分配的占據(jù)內(nèi)存
Dalvik Other:類數(shù)據(jù)結(jié)構(gòu)和索引占據(jù)內(nèi)存
Stack:棧內(nèi)存
Private Dirty:它基本上是進程內(nèi)不能被分頁到磁盤的內(nèi)存,也不和其他進程共享,private Dirty內(nèi)存是最重要的部分,因為只被自己進程使用
Private Clean:是已經(jīng)映射持久文件使用的內(nèi)存頁(例如正在被執(zhí)行的代碼),因此一段時間不使用的話就可以置換出去
Heap Alloc:是Dalvik堆和本地堆分配使用的大小,它的值比Pss Total和Private Dirty大,因為進程是從Zygote中復制分裂出來的,包含了進程共享的分配部分
Ashmem:不以dalvik-開頭的內(nèi)存區(qū)域,匿名共享內(nèi)存用來提供共享內(nèi)存通過分配一個多個進程,Android匿名共享內(nèi)存是基于Linux共享內(nèi)存的,都是在tmpfs文件系統(tǒng)上新建文件,并將其映射到不同的進程空間,從而達到共享內(nèi)存的目的,只是,Android在Linux的基礎(chǔ)上進行了改造,并借助Binder+fd文件描述符實現(xiàn)了共享內(nèi)存的傳遞。
Other dev:內(nèi)部driver占用的內(nèi)存
.so mmap:C 庫代碼占用的內(nèi)存
.jar mmap:Java 文件代碼占用的內(nèi)存
.apk mmap:apk代碼占用的內(nèi)存
.ttf mmap:ttf 文件代碼占用的內(nèi)存
.dex mmap:Dex 文件代碼占用的內(nèi)存
Other mmap:其他文件占用的內(nèi)存
8、 測試場景選擇
內(nèi)存出現(xiàn)泄漏的前提條件一定是有新的內(nèi)存分配,所以測試場景會選擇有新對象創(chuàng)建的場景,并結(jié)合用戶的使用場景和頻率來確定優(yōu)先級。測試場景主要有以下三種情況,配合測試次數(shù),然后可以每5次獲取一次內(nèi)存值進行判斷,一般測試300次,如果各種內(nèi)存測試完成并等待5分鐘后內(nèi)存沒有釋放,則高概率存在內(nèi)存泄露:
1)新畫面打開
由于新的畫面打開,就會創(chuàng)建新的Activity和View,并有許多其他對象被創(chuàng)建。
測試方法:
反復進入退出需要測試的目標Activity,如果發(fā)現(xiàn)Activities和Views的一直在增長,則內(nèi)存泄露一定發(fā)生(退出時如果手動GC,則Activities和Views的數(shù)量應(yīng)該為0)
2)畫面旋轉(zhuǎn)
當屏幕旋轉(zhuǎn)時,Orientation設(shè)置發(fā)生了改變,當前顯示的Activity會被重新創(chuàng)建。
測試方法:進入需要測試的目標Activity,反復橫豎屏切換,如果發(fā)現(xiàn)Activities數(shù)量等其他值一直在增長,則內(nèi)存泄露一定發(fā)生
3)滑動屏幕
滑動屏幕會使屏幕中顯示的對象(比如瀏覽器小說閱讀內(nèi)容)創(chuàng)建。
測試方法:進入需要測試的目標Activity,一直固定某個方向滑動(向左),如果發(fā)現(xiàn)內(nèi)存值一直在增長,則內(nèi)存泄露一定發(fā)生
Case例子,僅供參考:
測試過程中的值記錄模板,僅供參考:
注意:
1)每個應(yīng)用的腳本需要獲取的信息可以直接涉及好關(guān)聯(lián)應(yīng)用或進程的數(shù)據(jù)值,例如測試camera時后臺camera服務(wù)進程,多媒體進程、相冊進程。
2)針對內(nèi)存泄露的測試,需要開發(fā)自動化腳本測試,然后測試過程中獲取測試的值存入execl的固定模板,測試完成后根據(jù)測試結(jié)果數(shù)據(jù)判斷是否有內(nèi)存泄露
9、 定位內(nèi)存泄露的原因(如果是真機測試,安裝一個debug版本的apk,否則monitor無法顯示進程)
方法一:使用DDMS(Monitor)檢測內(nèi)存泄露--需要
步驟2、然后在打開DDMS, 選擇Heap標簽,然后點擊Cause GC按鈕,點擊Cause GC是手動觸發(fā)JAVA垃圾回收器,如下圖:
如果我們要測試某個Activity是否發(fā)生內(nèi)存泄露,我們可以反復進入和退出這個Activity, 再手動觸發(fā)幾次垃圾回收,觀察上圖中 data object這一欄中的 Total Size的大小是保持穩(wěn)定還是有明顯的變大趨勢,如果有明顯的變大趨勢就說明這個Activity存在內(nèi)存泄露的問題,需要在具體分析。
總結(jié)
以上是生活随笔為你收集整理的离开当前屏幕的判断方法_Android App内存泄露测试方法总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: build 之前执行task_一次NPM
- 下一篇: android7.1开机监听广播,And