android studio dump java heap_Android Studio 3.0 Memory Profiler使用
Memory Profiler是Android Profiler中的一個(gè)組件,Android Profiler是Android Studio3.0用來替換之前Android Monitor的觀察工具,主要用來觀察內(nèi)存,網(wǎng)絡(luò),cpu溫度。今天著重介紹其中的Memory Profiler。它能夠讓你識(shí)別出來內(nèi)存泄漏和內(nèi)存抖動(dòng),導(dǎo)致應(yīng)用卡頓,anr和crash. 它可以給你展示一個(gè)內(nèi)存使用的真實(shí)圖表,讓你知道當(dāng)時(shí)內(nèi)存使用情況,還能強(qiáng)制內(nèi)存回收,和跟蹤內(nèi)存分配.
如何打開Memory Profiler?
image.png
最后進(jìn)入Memory Profiler
image.png
為什么要去觀察應(yīng)用內(nèi)存的使用情況?
剛才也提到了Memory Profiler是用來解決內(nèi)存分配中產(chǎn)生抖動(dòng),導(dǎo)致應(yīng)用卡頓,anr和crash問題. 在Android系統(tǒng)內(nèi)存管理上,它是提供一套內(nèi)存回收機(jī)制去回收無用的對(duì)象,其實(shí)就是Dalvik虛擬機(jī)的垃圾回收器,當(dāng)垃圾回收器啟動(dòng)回收機(jī)制的時(shí)候,其實(shí)會(huì)對(duì)應(yīng)用的運(yùn)行產(chǎn)生一點(diǎn)影響,但是這種影響來說一般微乎其微,察覺不到。但是如果你的內(nèi)存分配比垃圾回收快很多,這種情況可能導(dǎo)致垃圾回收器回收內(nèi)存不及時(shí),從而導(dǎo)致應(yīng)用出現(xiàn)卡頓的現(xiàn)象.(這其實(shí)就是內(nèi)存抖動(dòng)所產(chǎn)生的影響). 另外一個(gè)問題就是內(nèi)存泄漏,內(nèi)存的持續(xù)泄漏可能導(dǎo)致內(nèi)存溢出,從而app運(yùn)行出現(xiàn)outofmem異常。
Memory Profiler通過以下方面防治上面出現(xiàn)的問題:
1,觀察不必要的內(nèi)存分配。(這種內(nèi)存分配導(dǎo)致效率降低)
2,Dump the Java heap 去觀察指定時(shí)間對(duì)象的在內(nèi)存中的分配情況,若干次Dump能夠幫助你發(fā)現(xiàn)內(nèi)存泄漏
3,測(cè)試極端的用戶交互情況下的內(nèi)存分配(比如說狂點(diǎn)某個(gè)請(qǐng)求按鈕),看看內(nèi)存使用情況如何,是否出現(xiàn)內(nèi)存抖動(dòng).
Memory Profiler主面板介紹
image.png
1:強(qiáng)制內(nèi)存回收按鈕
2:Dump the Java heap
3:開始/停止記錄內(nèi)存分配情況
4:縮小/放大時(shí)間線
5,實(shí)時(shí)播放內(nèi)存分配情況(這個(gè)按鈕點(diǎn)下試試便清楚了)
6,發(fā)生一些事件的記錄(如Activity的跳轉(zhuǎn),事件的輸入,屏幕的旋轉(zhuǎn))
7,內(nèi)存使用時(shí)間線
包含多少內(nèi)存被使用(左邊的y軸),還有頂上的顏色標(biāo)記內(nèi)存的類型,右邊的y軸表明分配對(duì)象的個(gè)數(shù),另外出現(xiàn)垃圾回收事件會(huì)有一個(gè)小圖標(biāo).
關(guān)于頂部的幾種內(nèi)存類型介紹:
Java : java代碼分配的內(nèi)存
Native:c/c++代碼分配的內(nèi)存(有時(shí)候其實(shí)并沒有使用到c/c++代碼,但還是會(huì)有Native的內(nèi)存分配,因?yàn)锳ndroid Framework會(huì)去通過java代碼訪問一些需要使用Native的資源,如圖像資源Bitmap)
Graphics:圖像緩存等,包括GL surfaces, GL textures等.
Stack:棧內(nèi)存(包括java和c/c++)
Code:代碼的內(nèi)存分配(例如代碼,資源,libs等等)
Other:這個(gè)是連系統(tǒng)都不知道是什么類型的內(nèi)存,放在這里.
Allocated: jave分配的對(duì)象個(gè)數(shù) (在Android7.1和以下的設(shè)備,這個(gè)計(jì)數(shù)是在設(shè)備連接后開始,所以并不是app啟動(dòng)時(shí)候的計(jì)數(shù)。Android8.0或更高,在系統(tǒng)里面內(nèi)置的Profiler工具,所以無論什么時(shí)候連接,都是app啟動(dòng)時(shí)候的計(jì)數(shù))
如何觀察對(duì)象分配的情況?
我們需要關(guān)注如下信息:
1,什么類型對(duì)象被分配,分配了多大的空間
2,對(duì)象分配的棧調(diào)用,是在哪個(gè)線程中調(diào)用的
3,對(duì)象的釋放時(shí)間(只針對(duì)8.0+)
如果是8.0以上的設(shè)備,不需要點(diǎn)擊之前面板介紹中的按鈕3,就可以觀察某一段時(shí)間的內(nèi)存分配情況,如果是7.1或以下是需要點(diǎn)擊按鈕3開始和停止。
Android8.0觀察一段時(shí)間的內(nèi)存分配情況:
demo2.gif
Android7.1或以下觀察一段時(shí)間的內(nèi)存分配情況:
demo3.gif
在7.1以下設(shè)備和8.0在記錄對(duì)象個(gè)數(shù)上面也是有區(qū)別的,前者記錄是最大65535個(gè)最近使用的對(duì)象,8.0卻沒有這個(gè)限制.
當(dāng)分析結(jié)束后會(huì)彈出如下面板:
image.png
下面是重頭戲,查看對(duì)象分配情況,也就是我們前面提到需要關(guān)注什么類型對(duì)象被分配,分配了多大的空間。
1,在Class Name列看一下有沒有異常分配的對(duì)象,個(gè)數(shù)很多,占用內(nèi)存比較大。點(diǎn)擊頭部Class Name進(jìn)行一個(gè)按字母排序操作,點(diǎn)擊Class Name面板下面的類名可以看到Instance View面板詳細(xì)的對(duì)象信息.
2,點(diǎn)擊Instance View面板中的對(duì)象,可以看到調(diào)用棧信息和調(diào)用的線程.
3,在Call Stack中點(diǎn)擊可以跳轉(zhuǎn)到實(shí)際的代碼.
以上是捕獲一段時(shí)間的內(nèi)存分配情況,如果想捕獲一瞬間的內(nèi)存分配需要用到heap dump.
捕獲一個(gè)heap dump
捕獲一個(gè)heap dump觀察某一個(gè)時(shí)間點(diǎn)的對(duì)象分配情況,注意之前介紹是一個(gè)時(shí)間段,而這里是時(shí)間點(diǎn)。它有助于幫助我們分析內(nèi)存泄漏,比如當(dāng)我應(yīng)用使用一段時(shí)候后,捕獲了一個(gè)heap dump,這個(gè)heap dump里面發(fā)現(xiàn)了并不應(yīng)該存在的對(duì)象分配情況,這說明是存在內(nèi)存泄漏的。通過一個(gè)heap dump你可以看到以下內(nèi)容:
1,你的app分配了什么樣的對(duì)象類型,每個(gè)類型分配了多少個(gè)數(shù)和大小。
2,使用了多少內(nèi)存
3,每個(gè)對(duì)象在代碼中的使用位置
4,對(duì)象分配的調(diào)用棧情況
捕獲一個(gè)heap dump在工具欄中點(diǎn)擊之前面板介紹中的按鈕2,稍等一會(huì)兒便能夠看到類似于之前記錄內(nèi)存分配后的面板彈出。
image.png
在上面圖片中可以看到如下列:
Class Name : 這個(gè)很好理解,就是類名
Alloc Count : 對(duì)象個(gè)數(shù)
Native Size : c/c++層內(nèi)存大小(bytes)
Shallow Size : java層內(nèi)存大小(bytes)
Retained Size : 這個(gè)是這個(gè)類中所引用到的對(duì)象的總大小 * 該類對(duì)象的個(gè)數(shù)
當(dāng)點(diǎn)擊app heap下拉列表會(huì)出現(xiàn)3個(gè)選項(xiàng)
Default heap: 這個(gè)我也不太明白是什么意思
App heap: app中的堆分配
Image heap: 圖像的堆分配
Zygote heap: 這個(gè)按照官方的解釋是來自安卓系統(tǒng)fork進(jìn)程的地方產(chǎn)生的寫數(shù)據(jù)備份
當(dāng)點(diǎn)擊Arrange by class下拉列表會(huì)出現(xiàn)3個(gè)選項(xiàng)
Arrange by class:根據(jù)類名進(jìn)行分組
Arrange by package:根據(jù)包名進(jìn)行分組
Arrange by callstack:根據(jù)調(diào)用棧進(jìn)行分配(這個(gè)目前也不是太理解)
當(dāng)我們點(diǎn)擊其中一個(gè)類的時(shí)候會(huì)彈出一個(gè)新的Instance View面板,如下圖:
image.png
每列中包括以下:
Depth: GC root到達(dá)該實(shí)例的最短跳數(shù).
Native Size: c/c++層中內(nèi)存的大小(bytes)
Shallow Size:java層內(nèi)存大小(bytes)
Retained Size:這個(gè)類中所引用到的對(duì)象的總大小(bytes)
另外補(bǔ)充一下,heap dump是看不到調(diào)用棧信息的.也就是上圖中的Call Stack面板.
分析你的heap,按照一下步驟.
1,瀏覽Class Name列表,看看有沒有大量對(duì)象存在,并且這些對(duì)象你認(rèn)為是不應(yīng)該存在的,可能存在內(nèi)存泄漏的情況. 點(diǎn)擊類名可以看到詳細(xì)的對(duì)象信息.
2,在這個(gè)Instance View面板中,點(diǎn)擊一個(gè)實(shí)例References面板就會(huì)顯示出來,里面都是使用該Instance的Reference,點(diǎn)擊剪頭可以看到引用它的所有區(qū)域。點(diǎn)擊鼠標(biāo)右鍵可以選擇go to instance去看到引用該引用的引用,或者jump to source去看調(diào)用的源代碼.
另外heap dump也是可以保存成為HPROF文件的,點(diǎn)擊如下按鈕即可保存起來,用于以后分析,或用作其它工具分析.
image.png
一般出現(xiàn)內(nèi)存泄漏的原因有:
1,長期引用到Activity,Context,View,Drawable的對(duì)象。
2,非靜態(tài)的內(nèi)部類,例如Runnable它可以引用到Activity的實(shí)例
3,一些長期緩存對(duì)象
下面舉一個(gè)例子具體分析一下如何使用Memory Profiler查找內(nèi)存泄漏.
查找內(nèi)存泄漏有以下幾個(gè)方式
1,一般我排查內(nèi)存泄漏的方式是,啟動(dòng)應(yīng)用,看一下當(dāng)前內(nèi)存使用了多少,使用應(yīng)用一段時(shí)間后(當(dāng)然你不想親自動(dòng)手點(diǎn)來點(diǎn)去,也可以使用monkey進(jìn)行一次自動(dòng)化測(cè)試), 退回到應(yīng)用首頁,看看當(dāng)前內(nèi)存又是多少。進(jìn)行一次heap dump, 看看結(jié)果,分析一下有沒有可疑的對(duì)象分配(比如說大量重復(fù)的Activity,同一個(gè)類型對(duì)象比較多,對(duì)象內(nèi)存占用較大).
2,發(fā)現(xiàn)可疑點(diǎn)后,通過分析結(jié)果,可以找到相應(yīng)代碼,找到代碼當(dāng)然也能找到使用代碼的場景,例如是Activity泄漏,反復(fù)進(jìn)行畫面的跳轉(zhuǎn)(如果你的應(yīng)用支持橫豎平切換的話,也可以反復(fù)旋轉(zhuǎn)屏幕),然后強(qiáng)制gc回收,看看內(nèi)存是否存在只增不減的情況.
3,也可以使用allocation跟蹤一段時(shí)間內(nèi)存分配情況,拿出來做分析
4,最后推薦一款leakcanary工具使用(具體可看:https://github.com/square/leakcanary)
當(dāng)然如果時(shí)間允許的話,以上每個(gè)步驟都需要進(jìn)行詳細(xì)測(cè)試。
下面開始正式的栗子:
我啟動(dòng)了一個(gè)疑似存在內(nèi)存泄漏app,然后使用了一段時(shí)間,進(jìn)行了一次heap dump, 結(jié)果如下
image.png
很明顯我發(fā)現(xiàn)了一個(gè)可疑的類OutOfMemActivity, 它存在多個(gè)實(shí)例,實(shí)際上在已知該app業(yè)務(wù)邏輯中是不應(yīng)該會(huì)有這么多OutOfMemActivity實(shí)例的,于是我變點(diǎn)開它的Instance View.
可疑點(diǎn)如紅色剪頭所指,因?yàn)橥獠款悓?shí)例引用到Activity都是不正常的操作,這里Broadcast的實(shí)例引用到了Activity.
image.png
點(diǎn)擊跳轉(zhuǎn)到源碼,發(fā)現(xiàn)是內(nèi)部類引用到外部類實(shí)例(Activity)的情況導(dǎo)致了內(nèi)存泄漏.
image.png
其實(shí)引起內(nèi)存泄漏的情況還有很多,這里就不一一列舉,上面只是展示一下Memory Profiler這個(gè)工具的使用.
總結(jié)
以上是生活随笔為你收集整理的android studio dump java heap_Android Studio 3.0 Memory Profiler使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谁能分享一下美剧权力的游戏第八季未删减的
- 下一篇: 复联3百度云,谢谢您!