內存泄漏是引發Android應用崩潰常見的緣由,每一個Android開發人員都應該明白怎麼避免發送。 經常使用的分析內存的工具備 Android Profiler 和 LeakCanary。java
Android Profiler 是Android Studio提供的一個工具,用於實時觀察應用的狀況,包括:內存、CPU、網絡等。android
LeakCanary 是一個第三方庫,用於分析內存泄漏。官方地址:square.github.io/leakcanary/git
是什麼致使了內存泄漏呢?當你的代碼爲一個對象分配了內存,可是卻沒有釋放,就會形成內存泄漏,固然沒有釋放的緣由有不少種。github
不論是什麼緣由,沒有釋放,是由於這個對象依然被別的對象引用,可是這些被引用的對象應該是要被銷燬的。網絡
Android 爲每一個應用限制的最大內存使用量,當使用的內存超過最大值之後就會引起OOM,是程序奔潰,因此咱們要嚴格限制內存的使用。框架
系統回收內存的時候,你的程序會暫停,但一般這個過程是很是短暫的,通常用戶感知不到。ide
可是有的時候你注意到你的程序變的緩慢和掉針,這是由於回收內存已經趕不上分配內存的速度了。工具
當內存泄漏發生的時候,內存會不斷的增長,致使不斷的觸發gc,進而致使程序卡頓,甚至系統會強制殺死你的程序已便回收內存。字體
基於這些緣由,咱們必須的關注內存。優化
Java內存模型分爲Jvm內存模型和Jmm內存模型。Jvm是java虛擬機內存模型,而Jmm內存模型是隻爲java程序服務。咱們一般討論的Java內存模型,更多的是在討論Jvm。
Jvm內存模型中按照線程是否獨佔,能夠分爲兩部分。線程獨佔內存區有棧,本地方法棧和程序計數器,全部線程共享的有堆和方法區。
咱們可使用Android Sudio的 Memory Profiler 中查看App的內存狀況。
內存計數中的類別以下:
Java:從 Java 或 Kotlin 代碼分配的對象的內存。
Native:從 C 或 C++ 代碼分配的對象的內存。 即便您的應用中不使用 C++,您也可能會看到此處使用的一些原生內存,由於 Android 框架使用原生內存表明您處理各類任務,如處理圖像資源和其餘圖形時,即便您編寫的代碼採用 Java 或 Kotlin 語言。
Graphics:圖形緩衝區隊列向屏幕顯示像素(包括 GL 表面、GL 紋理等等)所使用的內存。(請注意,這是與 CPU 共享的內存,不是 GPU 專用內存。)
Stack:您的應用中的原生堆棧和 Java 堆棧使用的內存。這一般與您的應用運行多少線程有關。
Code:您的應用用於處理代碼和資源(如 dex 字節碼、通過優化或編譯的 dex 代碼、.so 庫和字體)的內存。
Others:您的應用使用的系統不肯定如何分類的內存。
Allocated:您的應用分配的 Java/Kotlin 對象數。此數字沒有計入 C 或 C++ 中分配的對象。
若是鏈接到搭載 Android 7.1 及更低版本的設備,只有在 Memory Profiler 鏈接到您運行的應用時,纔開始此分配計數。所以,您開始分析以前分配的任何對象都不會被計入。不過,Android 8.0 及更高版本附帶一個設備內置分析工具,該工具可跟蹤全部分配,所以,在 Android 8.0 及更高版本上,此數字始終表示您的應用中待處理的 Java 對象總數。
Android 中常見的內存泄漏來自Activity,Service,View等組件的不當使用。好比當一個Activity在被銷燬後,還被別的對象持有的狀況下,gc就無法回收這個activity,致使內存泄漏。 咱們來看一個內存泄漏的例子:
class MemoryLeakDemoActivity : AppCompatActivity() {
companion object {
private var activities: MutableList<Activity>? = mutableListOf()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_memory_leak_demo)
// 這會形成內存泄漏
activities?.add(this)
}
}
複製代碼
這段代碼中,在onCreate方法咱們把當前activity對象加入到單例列表中,這樣當這個activity被銷燬後,卻不能被gc回收,由於其對象還在被引用,這就形成了內存的泄漏。
Android 對內存的要求的比較嚴格,每一個應用程序可以使用的內存都是有限的,不合理的使用內存會形成程序卡頓,甚至崩潰,因此每個開發者都應該要關注內存的使用狀況。