android中momery检测,Android性能优化第(二)篇---Memory Monitor检测内存泄露
版權聲明:本文為LooperJing原創文章,轉載請注明出處!
多練習多寫代碼.jpg
上篇說了一些性能優化的理論部分,主要是回顧一下,有了理論,小平同志又講了,實踐是檢驗真理的唯一標準,對于內存泄露的問題,現在通過Android Studio自帶工具Memory Monitor 檢測出來。性能優化的重要性不需要在強調,但是要強調一下,我并不是一個老司機,嘿嘿!沒用過這個工具的,請睜大眼睛。如果你用過,那么就不用在看這篇博客了。
先看一段會發生內存泄露的代碼
public class UserManger {
private static UserManger instance;
private Context context;
private UserManger(Context context) {
this.context = context;
}
public static UserManger getInstance(Context context) {
if (instance == null) {
instance = new UserManger(context);
}
return instance;
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
UserManger userManger = UserManger.getInstance(this);
}
}
代碼很簡單,就是一個單利模式泄露的場景,我們現在的關心的不是代碼本身,而是如何將代碼里面的內存泄露給找出來。但是對于上面的代碼發生內存泄露的原因還是有必要提一下。
上篇博客說了,內存泄漏產生的原因是:當一個對象已經不需要再使用了,本該被回收時,而有另外一個正在使用的對象持有它的引用從而就導致,對象不能被回收。這種導致了本該被回收的對象不能被回收而停留在堆內存中,就產生了內存泄漏。
在上面的代碼中,發生泄露的不是UserManger,而是MainActivity,UserManger中有一個靜態成員instance,其生命周期和應用程序的生命周期一致,當退出應用時,才能被銷毀,但是當GC準備回收MainActivity時,結果呢MainActivity的對象(this)在被UserManger所引用,UserManger本身又不能被干掉,所以就發生了內存泄露。
monitors.png
Memory Monitor是Android Monitors中的一種,Monitors主要包括四種,Memory Monitor ,CPU Monitor ,NetWork Monitor, GPU Monitor ,今天介紹的是Memory Monitor ,其他的Monitor,在后面也準備講。
Memory Monitor界面
Memory Monitor.png
圖中水平方向是時間軸,豎直方向是內存的分配情況
圖中深藍色的區域,表示當前正在使用中的內存總量,淺藍色或者淺灰色區域,表示空閑內存或者叫作未分配內存。
左上角工具欄三個圓圈按鈕依次代表
GC按鈕 ,可以手動GC,回收程序垃圾
內存快照(Dump Java Heap) ,點擊可以生成一個文件(包名+日期+“.hprof”),可以記錄摸一個時間點內,程序內存的情況
Allocation Traking ,點擊一次開始, 再次點擊結束,也可以可以生成一個文件。
回到我們的程序,多點擊幾次GC,看一下這個應用的內存使用情況。
內存使用情況.jpg
可以看到現在已經分配的內存有19.68M,我把手機旋轉一下,在看。
旋轉后內存使用情況.png
可以看到現在的內存使用量是21.09M,還是一樣的界面,卻多了1.41M!!!這很關鍵。
接下來,我們找一下,哪里發生了泄露。點擊Dump Java Heap,生成快照文件tool.test.memory.memoryleak_2016.11.13_21.38.hprof,Android Studio 自動彈出HPROF Viewer來分析它。
快照文件分析.png
現在介紹一下HPROF Viewer的用法
HPROF Viewer查看方式
左上角兩個紅框,是可選列表, 分別是用來選擇Heap區域, 和Class View的展示方式的.
Heap類型分為:
App Heap -- 當前App使用的Heap
Image Heap -- 磁盤上當前App的內存映射拷貝
Zygote Heap -- Zygote進程Heap(每個App進程都是從Zygote孵化出來的, 這部分基本是framework中的通用的類的Heap)
Class List View -- 類列表方式
Package Tree View -- 根據包結構的樹狀顯示
我通常點擊App heap下面的Classs Name把Heap中所有類按照字母順序排序,然后按照字母順序查找。
HPROF Viewer主要分ABC三大板塊
板塊A:這個應用中所有類的名字
版塊B:左邊類的所有實例
板塊C:在選擇B中的實例后,這個實例的引用樹
A板塊左上角列名解釋
列名
解釋
Class Name
類名,Heap中的所有Class
Total Count
內存中該類這個對象總共的數量,有的在棧中,有的在堆中
Heap Count
堆內存中這個類 對象的個數
Sizeof
每個該實例占用的內存大小
Shallow Size
所有該類的實例占用的內存大小
Retained Size
所有該類對象被釋放掉,會釋放多少內存
B板塊右上角上角列名解釋
列名
解釋
Instance
該類的實例
Depth
深度, 從任一GC Root點到該實例的最短跳數
Dominating Size
該實例可支配的內存大小
B板塊右上角有個"的按鈕, 點擊會進入HPROF Analyzer的hprof的分析界面:
Analyzer Tasks.png
"
在這個界面中可以直接把內存泄露可能的類找出來。
下面分析一下MainActivity的泄露情況
MainActivity發生內存泄露.png
一個Activity應該只有一個實例,但是從A區域來看 total count的值為2,heap count的值也為2,說明有一個是多余的。
在B區域中可以看見兩個MainActivity的實例,點擊一個看他的引用樹情況
在C區域中可以看到MainActivity的實例Context被UserManger的 instance引用了,引用深度為1.
在Analyzer Tasks 區域中,直接告訴你Leaked Activities,MainActivity包含其中
多方面的證據表明MainActivity發生了內存泄露
解決方案
public class UserManger {
private static UserManger instance;
private Context context;
private UserManger(Context context) {
this.context = context;
}
public static UserManger getInstance(Context context) {
if (instance == null) {
if(context!=null){
instance = new UserManger(context.getApplicationContext());
}
}
return instance;
}
}
不要用Activity的Context,因為Activity隨時可能被回收,我們用Application的Context,Application的Context的生命周期是整個應用,不回收也沒有關系。
Memory Monitor獲得內存的動態視圖,Heap Viewer顯示堆內存中存儲了什么,可惜Heap Viewer不能顯示你的數據具體分配在代碼的何處,如果還不過癮,想知道具體是哪些代碼使用了內存,還有一個功能是Allocation Tracker,用來內存分配追蹤。在內存圖中點擊途中標紅的部分,啟動追蹤,再次點擊就是停止追蹤,隨后自動生成一個alloc結尾的文件,這個文件就記錄了這次追蹤到的所有數據,然后會在右上角打開一個數據面板
Allocation Tracker啟動追蹤
Allocation Tracker啟動追蹤.png,
Allocation Tracker查看方式
Allocation Tracker查看方式
有兩種查看方式,默認是Group by Method方式
Group by Method:用方法來分類我們的內存分配
Group by Allocator:用內存分配器來分類我們的內存分配
從上圖可以看出,首先以線程對象分類,Size是內存大小,Count是分配了多少次內存,點擊一下線程就會查看每個線程里所有分配內存的方法
Group by Method方式
每個線程里所有分配內存的方法.png
OK,-Memory Monitor
** Group by Allocator方式**
EY%HY_B74%BUE22C6$G~CTP.png
右鍵可以直接跳到源碼
- 扇形統計圖
AQFHT$@7TYP0S_1`DU@%S%6.png
點擊統計圖按鈕,會生成上圖,扇形統計圖是以圓心為起點,最外層是其內存實際分配的對象,每一個同心圓可能被分割成多個部分,代表了其不同的子孫,每一個同心圓代表他的一個后代,每個分割的部分代表了某一帶人有多人,你雙擊某個同心圓中某個分割的部分,會變成以你點擊的那一代為圓心再向外展開。
除了扇形圖,還有柱狀圖可選擇,可以自己操作,OK,Memory Monitor到此結束,下一篇性能優化部分博客仍然是檢測內存泄露,明天上班,晚安!
總結
以上是生活随笔為你收集整理的android中momery检测,Android性能优化第(二)篇---Memory Monitor检测内存泄露的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数组元素替换_Linux Shell 通
- 下一篇: android 会话 java_java