Android內(nèi)存分析工具:Memory Profiler

一视搏、前言

我們知道碉就,Android系統(tǒng)檢測到app有不再使用對象時回梧,就會進行內(nèi)存回收相關(guān)的工作废岂。

盡管Android檢測無用對象、回收內(nèi)存的方法在不斷改進狱意,

但在目前所有的Android版本中湖苞,進行上述工作時,系統(tǒng)仍需要短暫地停止app的運行详囤。

在大多數(shù)情況下财骨,系統(tǒng)進行內(nèi)存回收的行為是無法被用戶察覺到的。

然而纬纪,如果應(yīng)用分配內(nèi)存的速度大于系統(tǒng)回收的速度蚓再,

那么app進程的正常運行可能就回受到影響。

畢竟包各,系統(tǒng)必須回收到足夠的供app需要的內(nèi)存,才會恢復(fù)處于暫停狀態(tài)的app靶庙。

在這種情況下问畅,app就可能出現(xiàn)掉幀、卡頓等現(xiàn)象。

在更嚴(yán)重的情況下护姆,如果出現(xiàn)了內(nèi)存泄露的問題矾端,那么系統(tǒng)中就可能堆積無法釋放的內(nèi)存,

使得系統(tǒng)必須更加頻繁地進行內(nèi)存回收卵皂,從而降低系統(tǒng)的性能秩铆。

甚至在極端條件下,系統(tǒng)不得不殺死部分正在后臺運行的app進程灯变。

于是用戶將后臺應(yīng)用移到前臺時殴玛,卻發(fā)現(xiàn)應(yīng)用無故重啟,這顯然帶來了較差的用戶體驗添祸。

由此可見滚粟,內(nèi)存對于app而言,是極其關(guān)鍵的性能指標(biāo)刃泌。

目前凡壤,分析app內(nèi)存的工具有很多,

本文主要記錄一下Android Studio內(nèi)置的內(nèi)存分析工具Memory Profiler耙替。

二亚侠、基本介紹

Memory Profiler是Android Profiler的一個組件, 用于幫助分析內(nèi)存泄露和內(nèi)存抖動的問題俗扇。

當(dāng)PC連接Android L以上的設(shè)備時硝烂,該工具才能夠正常使用。

Memory Profiler的功能包括:

展示應(yīng)用內(nèi)存使用情況的實時圖像狐援、抓取內(nèi)存的dump信息钢坦、強制垃圾回收及追蹤內(nèi)存分配。

2.1 開啟步驟

打開Memory Profiler的步驟為:

1啥酱、 依次點擊Android Studio的View → Tool Windows → Android Profiler爹凹,

或直接點擊工具欄Android Profiler對應(yīng)的圖標(biāo);

2镶殷、 PC連接Android終端后禾酱,在Android Profiler對應(yīng)的區(qū)域選擇接的設(shè)備和需要監(jiān)控的進程:


3、 點擊Android Profiler界面中MEMORY區(qū)域的任意位置绘趋,即可開啟Memory Profiler颤陶,如下圖所示:


需要注意的是,如果PC連接Android 7.1以下的設(shè)備時陷遮,有些關(guān)鍵數(shù)據(jù)可能無法被Android Profiler統(tǒng)計滓走,

此時Android Profiler會顯示如下信息:


這時我們需要依次點擊Android Studio的Run → Edit Configurations → Profiling 按鍵,選中app后點擊Enabled advanced profiling帽馋,

如下圖所示:


為了支持該功能搅方,要求app對應(yīng)的gradle版本必須在2.4以上比吭。

2.2 界面介紹

打開Memory Profiler后,主界面如下所示(為了方便姨涡,這里直接盜取Android技術(shù)文檔中的圖):


其中:

標(biāo)注1對應(yīng)的按鍵用于強制內(nèi)存回收衩藤。

標(biāo)注2對應(yīng)的按鍵用于抓取進程內(nèi)存的dump信息。

標(biāo)注3對應(yīng)的按鍵用于記錄內(nèi)存的分配信息(連接Android 7.1及以下才會有此按鍵)涛漂。

初次點擊時赏表,對應(yīng)統(tǒng)計的開始時間點;再次點擊時匈仗,對應(yīng)統(tǒng)計的結(jié)束時間點瓢剿。

進程在兩個時間點之間的內(nèi)存分配信息,將被Memory Profiler記錄和分析锚沸。

標(biāo)注4對應(yīng)的區(qū)域用于縮放時間軸跋选。

標(biāo)注5對應(yīng)的按鍵用于顯示實時的內(nèi)存數(shù)據(jù)。

標(biāo)注6對應(yīng)的區(qū)域用于記錄事件發(fā)生的時間點及大致持續(xù)的時間(例如activity狀態(tài)改變哗蜈、用戶操作界面等事件)前标。

標(biāo)注7對應(yīng)的區(qū)域用于顯示內(nèi)存使用情況對應(yīng)的時間軸(與標(biāo)注6結(jié)合,就可以看出各事件帶來的內(nèi)存變化情況)距潘。

需要說明的是炼列,標(biāo)注7對應(yīng)區(qū)域顯示的內(nèi)容包括:

不同類型內(nèi)存占用情況對應(yīng)的圖像;

分配對象數(shù)量對應(yīng)的短畫線音比;

內(nèi)存回收事件發(fā)生的時機俭尖。

2.3 統(tǒng)計的數(shù)據(jù)類型及含義

Memory Profiler主要根據(jù)Android系統(tǒng)提供的信息,

統(tǒng)計app獨自占用內(nèi)存洞翩,即不統(tǒng)計app與系統(tǒng)或其它app共有的內(nèi)存稽犁。

Memory Profiler統(tǒng)計內(nèi)存的種類如下圖所示:


如上圖所示,其中:

Java表示Java代碼或Kotlin代碼分配的內(nèi)存骚亿;

Native表示C或C++代碼分配的內(nèi)存(即使App沒有native層已亥,調(diào)用framework代碼時,也有可能觸發(fā)分配native內(nèi)存)来屠;

Graphics表示圖像相關(guān)緩存隊列占用的內(nèi)存虑椎;

Stack表示native和java占用的棧內(nèi)存;

Code表示代碼俱笛、資源文件捆姜、庫文件等占用的內(nèi)存;

Others表示無法明確分類的內(nèi)存迎膜;

Allocated表示Java或Kotlin分配對象的數(shù)量(Android8.0以下時泥技,僅統(tǒng)計Memory Profiler啟動后,進程再分配的對象數(shù)量磕仅;

8.0以上時零抬,由于系統(tǒng)內(nèi)置了統(tǒng)計工具镊讼,Memory Profiler可以得到整個app啟動后分配對象的數(shù)量)宽涌。

三平夜、基本用法

對Memory Profiler有了基本的了解后,我們來看看它的基本用法卸亮。

3.1 查看內(nèi)存分配情況

Memory Profiler可以查看兩個時間點之間的內(nèi)存分配情況忽妒,包括:

對象的類型、占用內(nèi)存的大小兼贸、棧信息等段直。

連接8.0以上的設(shè)備時,Memory Profiler還可以顯示對象被回收的時間溶诞。

PC連接8.0以上的設(shè)備時鸯檬,在內(nèi)存統(tǒng)計的時間線上,直接點擊和拖動就可以選擇觀察區(qū)域螺垢;

連接低版本的設(shè)備時喧务,則需要點擊Record Memory allocations按鍵(2.2小結(jié)介紹的標(biāo)注3)選擇觀察區(qū)域。

選定觀察區(qū)域后枉圃, Memory Profiler就可以統(tǒng)計這段時間內(nèi)app分配內(nèi)存的情況:


從圖中可以看出功茴,Memory Profiler可以顯示分配對象的類名;

點擊類后孽亲,會在Instance View顯示具體的對象坎穿;

點擊具體對象后,會在Call back區(qū)域顯示調(diào)用棧返劲。

點擊調(diào)用棧信息后玲昧,就會跳轉(zhuǎn)到具體的代碼。

3.2 查看內(nèi)存占用情況

點擊2.2小結(jié)介紹的標(biāo)注2篮绿,即可抓取點擊后一段時間內(nèi)app占用內(nèi)存的dump信息孵延。

通過dump信息,我們可以看到app當(dāng)前仍存在于內(nèi)存中的對象搔耕。

結(jié)合代碼隙袁,我們可以分析是否有本應(yīng)被析構(gòu)卻仍存活的泄露對象。

與統(tǒng)計內(nèi)存分配信息一樣弃榨,內(nèi)存占用信息同樣會顯示對象的類型菩收、數(shù)量、占用內(nèi)存的大小鲸睛、引用關(guān)系等娜饵。

如下圖所示:


圖中Alloc Count表示堆中分配對象的數(shù)量;

Shallow Size表示對象使用Java內(nèi)存的大小官辈,單位為byte箱舞;

Retained Size表示對象占用的實際內(nèi)存大小遍坟,大于等于Shallow Size;

7.0及以上版本的設(shè)備晴股,還會顯示對象占用的Native Size愿伴。

點擊具體的對象時,也會顯示Instance View电湘。

此時隔节,Instance View顯示的信息變多了,包括:

Depth表示當(dāng)前對象到任一GC root的最短跳數(shù)寂呛;

Shallow Size枝缔、Retained Size的含義與前文一致剧蹂。

同樣少态,7.0及以上版本的設(shè)備帖鸦,還會顯示對象占用的Native Size。

從圖中可以看出劫拢,Instance View不會顯示棧信息肉津。

如果想獲得棧信息的話,必須先點擊Record Memory allocations按鍵尚镰。

四阀圾、使用示例

利用Memory Profiler,我分析了一下某反病毒引擎SDK的內(nèi)存占用情況狗唉。

隨便寫了個demo初烘,繼承SDK后啟動app,內(nèi)存占用情況如下圖所示:


然后分俯,通過操作UI初始化SDK肾筐,發(fā)現(xiàn)穩(wěn)定后內(nèi)存占用情況如下圖所示:


比對前后兩圖,不考慮界面UI變化消耗的內(nèi)存缸剪,

可以看出:內(nèi)存增加的主體部分來自于Native函數(shù)吗铐,其它類型的內(nèi)存變化幾乎可以忽略。

這是因為該SDK初始化時杏节,最主要的工作是在Native層加載底層的so文件唬渗。

接下來,我們在demo里調(diào)用SDK的接口奋渔,批量掃描樣本镊逝,統(tǒng)計內(nèi)存消耗情況如下圖所示:


從圖中可以看出app消耗的內(nèi)存飆升到了104M,

與初始化后的內(nèi)存相比嫉鲸,其中增加主要是code和native類型的內(nèi)存撑蒜。

根據(jù)2.3小結(jié)的描述,我們知道code類型統(tǒng)計的是app進程需要的資源文件、庫文件等座菠,

因此這部分內(nèi)存主要是SDK中引擎加載病毒庫等消耗掉的內(nèi)存狸眼;

而Native內(nèi)存的消耗,應(yīng)該也是由于引擎掃描文件導(dǎo)致的浴滴。

按照3.1小結(jié)的描述拓萌,我們查看了一下批量掃描這段時間內(nèi),

app進程內(nèi)存分配的情況巡莹,如下圖所示:


容易看出司志,在這段時間內(nèi),除去native內(nèi)存外降宅,整個app分配內(nèi)存并不大,

且按照對象占用內(nèi)存的大小排序囚霸,排在前列的都是基本數(shù)據(jù)類型腰根。

因此,這段時間內(nèi)app進程的內(nèi)存應(yīng)該是比較正常的拓型。

我們進行GC操作额嘿,內(nèi)存情況如下圖所示:


發(fā)現(xiàn)內(nèi)存幾乎和掃描前一致,按照3.2小結(jié)進行dump分析劣挫,沒有發(fā)現(xiàn)泄露對象册养。

因此,可以確認(rèn)SDK不存在內(nèi)存泄露的問題(dump信息含有sdk的隱私压固,這里就不再附圖了)球拦。

五、總結(jié)

至此帐我,我們已經(jīng)介紹了Android Memory Profiler工具的基本情況坎炼,

并簡單列舉了該工具的使用方式。

個人感覺拦键,不同于LeakCanary谣光,

Android Memory Profiler更側(cè)重于宏觀場景下的內(nèi)存分析。

————————————————

版權(quán)聲明:本文為CSDN博主「ZhangJianIsAStark」的原創(chuàng)文章芬为,遵循 CC 4.0 BY 版權(quán)協(xié)議萄金,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/gaugamela/article/details/79027538

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末媚朦,一起剝皮案震驚了整個濱河市氧敢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莲镣,老刑警劉巖福稳,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瑞侮,居然都是意外死亡的圆,警方通過查閱死者的電腦和手機鼓拧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來越妈,“玉大人季俩,你說我怎么就攤上這事∶仿樱” “怎么了酌住?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長阎抒。 經(jīng)常有香客問我酪我,道長,這世上最難降的妖魔是什么且叁? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任都哭,我火速辦了婚禮,結(jié)果婚禮上逞带,老公的妹妹穿的比我還像新娘欺矫。我一直安慰自己,他們只是感情好展氓,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布穆趴。 她就那樣靜靜地躺著,像睡著了一般遇汞。 火紅的嫁衣襯著肌膚如雪未妹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天勺疼,我揣著相機與錄音教寂,去河邊找鬼。 笑死执庐,一個胖子當(dāng)著我的面吹牛酪耕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播轨淌,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼迂烁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了递鹉?” 一聲冷哼從身側(cè)響起盟步,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎躏结,沒想到半個月后却盘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年黄橘,在試婚紗的時候發(fā)現(xiàn)自己被綠了兆览。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡塞关,死狀恐怖抬探,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情帆赢,我是刑警寧澤小压,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站椰于,受9級特大地震影響怠益,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜廉羔,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一溉痢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧憋他,春花似錦、人聲如沸髓削。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽立膛。三九已至揪罕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宝泵,已是汗流浹背好啰。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留儿奶,地道東北人框往。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像闯捎,于是被迫代替她去往敵國和親椰弊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容