內存分析(in-memory analytics)是我們編寫速度快、效率高的代碼必不可少的知識。如果自己編寫的代碼在內存的分配一無所知,我想這樣的程序讓你去優化,應該是無從下手的。那么內存分析是什么?是指當數據存放在計算機的隨機存取存儲器(RAM)中時查詢數據的方式,和存儲在物理磁盤中的數據的查詢方式相反。隨着RAM成本的下降,內存分析對很多業務都變得可行。
Android的一些內存知識
垃圾回收(GC)
垃圾回收包含兩個過程:
1)判定階段,也就是判斷哪些對象可以被回收,
2)收集階段,是指具體的回收策略。
判定階段主要有兩種方式
1)引用計數,對象每多一個引用計數加1,少一個引用計數減1,計數為0時就表示這個對象可以被回收了。但是引用計數有個缺點,不能判斷循環應用的情況,所以就有了下面的方式
2)根搜索,從一些根對象(GCRoot)開始遍歷搜索,如果一個對象無法被搜索到,說明這個對象可以被回收了。
可以作為GCRoot的對象:
1 一些虛擬機棧中的對象;2 方法區中的類靜態屬性對象;3 方法區中的常量對象;4 Native棧中JNI的引用對象
收集階段主要有四種方式
1)標記清除,最簡單的算法,講標記好的對象直接清除,速度快,但效率不高,內存碎片
2)復制算法,每次使用可用內存的一半,收集時將可用對象復制到另一半內存,回收這一半
3)標記整理,將存活對象整理到內存區域的一端,剩余部分回收
4)分代回收,將內存區域按對象存活周期划分為青年代和老年代等,不同區域采用上面不同的收集算法。
Dalvik與ART
Android5.0 之前使用Dalvik虛擬機,之后使用ART虛擬機,下面是一些比較:
Dalvik在運行時將字節碼轉換為機器碼,ART在安裝的時候就轉換為機器碼,這樣安裝好的應用會占用更大的空間,但是運行時少了轉換的時間,所以運行更快
ART提供了更好的垃圾回收表現,將垃圾回收時,程序的暫停次數由兩次(分析、清理)減少到一次;程序暫停時,並行的進行垃圾回收處理;回收新近分配的、生命期短的對象,垃圾回收器花費的時間更少
Android內存分析工具
Memory Monitor
GC操作需要暫停其他線程,因此短時間頻繁的GC會對UI線程產生影響,導致頻繁GC一般有兩種情況,
大量的對象被創建又在短時間內馬上被釋放,比如在View的onDraw方法中創建對象
Young Generation的內存區域達到閥值,剩余空間不夠的時候,也會觸發頻繁GC
Android Studio提供了Memory Monitor來實時顯示應用運行時內存占用情況,下邊藍色部分是現在占用的內存,上面灰色的部分顯示是已回收的內存。如果在圖上看到尖峰,也就是快速分配內存又被回收,也就是發生了內存抖動,這里就是需要優化的地方。


Allocation Tracking
Allocation Tracking是DDMS中提供內存工具,用來顯示一段時間內的內存分配情況。

選擇要跟蹤的進程名,點擊Start Tracking開始跟蹤,做一些操作后點擊Get Allocations就可以將這段操作中新分配的對象顯示出來,點擊具體的對象可以在下面看到是哪一個方法分配的這個對象。
Heap Tool 與 MAT
Heap Tool可以查看當前的內存快照

從數據里可以看到當前內存的占用和回收情況,每次垃圾回收這里的數據都會更新,因為會不斷獲取內存數據刷新顯示,所以這時候對應用操作會出現卡頓。
Heap Tool提供的是一個內存的總體情況,圖表顯示的內容比較簡單,如果要具體分析的話最好生成.hprof文件,使用MAT工具進行分析。

關於MAT工具的使用已經有很多介紹,google官方曾經寫過一個使用介紹,有興趣可以上網查閱。
一般用到MAT工具分析內存都是因為發生了應用發生了內存泄漏,需要自己去分析可能泄漏的地方,然后用MAT工具去驗證。而最近Square公司開源了一個內存泄漏檢測項目LeakCanary,極大地簡化了這個過程,可以說是Android內存泄漏檢測的終極利器。
LeakCanary
A memory leak detection library for Android and java.

LeakCanary會檢測應用的內存回收情況,如果發現有垃圾對象沒有被回收,就會去分析當前的內存快照,也就是上邊MAT用到的.hprof文件,找到對象的引用鏈,並顯示在頁面上。
使用:
在build.gradle文件中添加
在應用的application onCreate方法中添加LeakCanary.install(this),如下
應用運行起來后,LeakCanary會自動去分析當前的內存狀態,如果檢測到泄漏會發送到通知欄,點擊通知欄就可以跳轉到具體的泄漏分析頁面。
Tips
就目前使用的結果來看,絕大部分泄漏是由於使用單例模式hold住了Activity的引用,比如傳入了context或者將Activity作為listener設置了進去,所以在使用單例模式的時候要特別注意,還有在Activity生命周期結束的時候將一些自定義監聽器的Activity引用置空。
關於LeakCanary的更多分析可以看項目主頁的介紹,還有這里http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
Reference
上文簡單介紹了Android的一些內存知識,主要是垃圾回收(GC)的過程、階段性方式和GCRoot的對象,還簡單說明一下Dalvik與ART這兩個虛擬機,最后詳細介紹了android內存分析工具,有Memory Monitor、 Allocation Tracking、Heap Tool 、 MAT和LeakCanary這幾個分析工具,還有一些使用方法和一些小提示,如果有興趣,可以參考下面給出的參考資料。
轉載地址:http://www.kokojia.com/article/19208.html