垃圾回收包含兩個過程:html
斷定階段,也就是判斷哪些對象能夠被回收,android
收集階段,是指具體的回收策略。git
斷定階段主要有兩種方式github
引用計數,對象每多一個引用計數加1,少一個引用計數減1,計數爲0時就表示這個對象能夠被回收了。可是引用計數有個缺點,不能判斷循環應用的狀況,因此就有了下面的方式算法
根搜索,從一些根對象(GCRoot)開始遍歷搜索,若是一個對象沒法被搜索到,說明這個對象能夠被回收了。
能夠做爲GCRoot的對象: 1 一些虛擬機棧中的對象;2 方法區中的類靜態屬性對象;3 方法區中的常量對象;4 Native棧中JNI的引用對象
ide
收集階段主要有四種方式工具
標記清除,最簡單的算法,講標記好的對象直接清除,速度快,但效率不高,內存碎片post
複製算法,每次使用可用內存的一半,收集時將可用對象複製到另外一半內存,回收這一半gradle
標記整理,將存活對象整理到內存區域的一端,剩餘部分回收優化
分代回收,將內存區域按對象存活週期劃分爲青年代和老年代等,不一樣區域採用上面不一樣的收集算法。
Android5.0 以前使用Dalvik虛擬機,以後使用ART虛擬機,下面是一些比較:
Dalvik在運行時將字節碼轉換爲機器碼,ART在安裝的時候就轉換爲機器碼,這樣安裝好的應用會佔用更大的空間,可是運行時少了轉換的時間,因此運行更快
ART提供了更好的垃圾回收表現,將垃圾回收時,程序的暫停次數由兩次(分析、清理)減小到一次;程序暫停時,並行的進行垃圾回收處理;回收新近分配的、生命期短的對象,垃圾回收器花費的時間更少
GC操做須要暫停其餘線程,所以短期頻繁的GC會對UI線程產生影響,致使頻繁GC通常有兩種狀況,
大量的對象被建立又在短期內立刻被釋放,好比在View的onDraw方法中建立對象
Young Generation的內存區域達到閥值,剩餘空間不夠的時候,也會觸發頻繁GC
Android Studio提供了Memory Monitor來實時顯示應用運行時內存佔用狀況,下邊藍色部分是如今佔用的內存,上面灰色的部分顯示是已回收的內存。若是在圖上看到尖峯,也就是快速分配內存又被回收,也就是發生了內存抖動,這裏就是須要優化的地方。
Allocation Tracking是DDMS中提供內存工具,用來顯示一段時間內的內存分配狀況。
選擇要跟蹤的進程名,點擊Start Tracking開始跟蹤,作一些操做後點擊Get Allocations就能夠將這段操做中新分配的對象顯示出來,點擊具體的對象能夠在下面看到是哪個方法分配的這個對象。
Heap Tool能夠查看當前的內存快照
從數據裏能夠看到當前內存的佔用和回收狀況,每次垃圾回收這裏的數據都會更新,由於會不斷獲取內存數據刷新顯示,因此這時候對應用操做會出現卡頓。
Heap Tool提供的是一個內存的整體狀況,圖表顯示的內容比較簡單,若是要具體分析的話最好生成.hprof文件,使用MAT工具進行分析。
關於MAT工具的使用已經有不少介紹,google官方曾經寫過一個使用介紹http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html,推薦一箇中文博客,
http://blog.csdn.net/guolin_blog/article/details/42238633,寫的很好。
通常用到MAT工具分析內存都是由於發生了應用發生了內存泄漏,須要本身去分析可能泄漏的地方,而後用MAT工具去驗證。而最近Square公司開源了一個內存泄漏檢測項目LeakCanary,極大地簡化了這個過程,能夠說是Android內存泄漏檢測的終極利器。
A memory leak detection library for Android and Java.
項目地址:https://github.com/square/leakcanary
LeakCanary會檢測應用的內存回收狀況,若是發現有垃圾對象沒有被回收,就會去分析當前的內存快照,也就是上邊MAT用到的.hprof文件,找到對象的引用鏈,並顯示在頁面上。
使用:
在build.gradle文件中添加
dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' }1234
在應用的Application onCreate方法中添加LeakCanary.install(this)
,以下
public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } }1234567
應用運行起來後,LeakCanary會自動去分析當前的內存狀態,若是檢測到泄漏會發送到通知欄,點擊通知欄就能夠跳轉到具體的泄漏分析頁面。
Tips:就目前使用的結果來看,絕大部分泄漏是因爲使用單例模式hold住了Activity的引用,好比傳入了context或者將Activity做爲listener設置了進去,因此在使用單例模式的時候要特別注意,還有在Activity生命週期結束的時候將一些自定義監聽器的Activity引用置空。
關於LeakCanary的更多分析能夠看項目主頁的介紹,還有這裏http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
http://sr1.me/way-to-explore/2014/06/20/what-is-art-to-android.html
http://www.infoq.com/cn/news/2014/07/art-runtime
http://android.jobbole.com/80926/
http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/