Android系統(tǒng) 內(nèi)存分析

內(nèi)存分析(in-memory analytics)是我們編寫速度快、效率高的代碼必不可少的知識(shí)。如果自己編寫的代碼在內(nèi)存的分配一無(wú)所知,我想這樣的程序讓你去優(yōu)化,應(yīng)該是無(wú)從下手的。那么內(nèi)存分析是什么?是指當(dāng)數(shù)據(jù)存放在計(jì)算機(jī)的隨機(jī)存取存儲(chǔ)器(RAM)中時(shí)查詢數(shù)據(jù)的方式,和存儲(chǔ)在物理磁盤中的數(shù)據(jù)的查詢方式相反。隨著RAM成本的下降,內(nèi)存分析對(duì)很多業(yè)務(wù)都變得可行。

Android的一些內(nèi)存知識(shí)

垃圾回收(GC)

垃圾回收包含兩個(gè)過(guò)程:

本帖隱藏的內(nèi)容

1)判定階段,也就是判斷哪些對(duì)象可以被回收,

2)收集階段,是指具體的回收策略。

判定階段主要有兩種方式

1)引用計(jì)數(shù),對(duì)象每多一個(gè)引用計(jì)數(shù)加1,少一個(gè)引用計(jì)數(shù)減1,計(jì)數(shù)為0時(shí)就表示這個(gè)對(duì)象可以被回收了。但是引用計(jì)數(shù)有個(gè)缺點(diǎn),不能判斷循環(huán)應(yīng)用的情況,所以就有了下面的方式

2)根搜索,從一些根對(duì)象(GCRoot)開(kāi)始遍歷搜索,如果一個(gè)對(duì)象無(wú)法被搜索到,說(shuō)明這個(gè)對(duì)象可以被回收了。

可以作為GCRoot的對(duì)象:

1 一些虛擬機(jī)棧中的對(duì)象;2 方法區(qū)中的類靜態(tài)屬性對(duì)象;3 方法區(qū)中的常量對(duì)象;4 Native棧中JNI的引用對(duì)象

收集階段主要有四種方式

1)標(biāo)記清除,最簡(jiǎn)單的算法,講標(biāo)記好的對(duì)象直接清除,速度快,但效率不高,內(nèi)存碎片

2)復(fù)制算法,每次使用可用內(nèi)存的一半,收集時(shí)將可用對(duì)象復(fù)制到另一半內(nèi)存,回收這一半

3)標(biāo)記整理,將存活對(duì)象整理到內(nèi)存區(qū)域的一端,剩余部分回收

4)分代回收,將內(nèi)存區(qū)域按對(duì)象存活周期劃分為青年代和老年代等,不同區(qū)域采用上面不同的收集算法。

Dalvik與ART

Android5.0 之前使用Dalvik虛擬機(jī),之后使用ART虛擬機(jī),下面是一些比較:

Dalvik在運(yùn)行時(shí)將字節(jié)碼轉(zhuǎn)換為機(jī)器碼,ART在安裝的時(shí)候就轉(zhuǎn)換為機(jī)器碼,這樣安裝好的應(yīng)用會(huì)占用更大的空間,但是運(yùn)行時(shí)少了轉(zhuǎn)換的時(shí)間,所以運(yùn)行更快

ART提供了更好的垃圾回收表現(xiàn),將垃圾回收時(shí),程序的暫停次數(shù)由兩次(分析、清理)減少到一次;程序暫停時(shí),并行的進(jìn)行垃圾回收處理;回收新近分配的、生命期短的對(duì)象,垃圾回收器花費(fèi)的時(shí)間更少

Android內(nèi)存分析工具

Memory Monitor

GC操作需要暫停其他線程,因此短時(shí)間頻繁的GC會(huì)對(duì)UI線程產(chǎn)生影響,導(dǎo)致頻繁GC一般有兩種情況,

大量的對(duì)象被創(chuàng)建又在短時(shí)間內(nèi)馬上被釋放,比如在View的onDraw方法中創(chuàng)建對(duì)象

Young Generation的內(nèi)存區(qū)域達(dá)到閥值,剩余空間不夠的時(shí)候,也會(huì)觸發(fā)頻繁GC

Android Studio提供了Memory Monitor來(lái)實(shí)時(shí)顯示應(yīng)用運(yùn)行時(shí)內(nèi)存占用情況,下邊藍(lán)色部分是現(xiàn)在占用的內(nèi)存,上面灰色的部分顯示是已回收的內(nèi)存。如果在圖上看到尖峰,也就是快速分配內(nèi)存又被回收,也就是發(fā)生了內(nèi)存抖動(dòng),這里就是需要優(yōu)化的地方。

Allocation Tracking

Allocation Tracking是DDMS中提供內(nèi)存工具,用來(lái)顯示一段時(shí)間內(nèi)的內(nèi)存分配情況。

選擇要跟蹤的進(jìn)程名,點(diǎn)擊Start Tracking開(kāi)始跟蹤,做一些操作后點(diǎn)擊Get Allocations就可以將這段操作中新分配的對(duì)象顯示出來(lái),點(diǎn)擊具體的對(duì)象可以在下面看到是哪一個(gè)方法分配的這個(gè)對(duì)象。

Heap Tool 與 MAT

Heap Tool可以查看當(dāng)前的內(nèi)存快照

從數(shù)據(jù)里可以看到當(dāng)前內(nèi)存的占用和回收情況,每次垃圾回收這里的數(shù)據(jù)都會(huì)更新,因?yàn)闀?huì)不斷獲取內(nèi)存數(shù)據(jù)刷新顯示,所以這時(shí)候?qū)?yīng)用操作會(huì)出現(xiàn)卡頓。

Heap Tool提供的是一個(gè)內(nèi)存的總體情況,圖表顯示的內(nèi)容比較簡(jiǎn)單,如果要具體分析的話最好生成.hprof文件,使用MAT工具進(jìn)行分析。

關(guān)于MAT工具的使用已經(jīng)有很多介紹,google官方曾經(jīng)寫過(guò)一個(gè)使用介紹,有興趣可以上網(wǎng)查閱。

一般用到MAT工具分析內(nèi)存都是因?yàn)榘l(fā)生了應(yīng)用發(fā)生了內(nèi)存泄漏,需要自己去分析可能泄漏的地方,然后用MAT工具去驗(yàn)證。而最近Square公司開(kāi)源了一個(gè)內(nèi)存泄漏檢測(cè)項(xiàng)目LeakCanary,極大地簡(jiǎn)化了這個(gè)過(guò)程,可以說(shuō)是Android內(nèi)存泄漏檢測(cè)的終極利器。

LeakCanary

A memory leak detection library for Android andjava.

LeakCanary會(huì)檢測(cè)應(yīng)用的內(nèi)存回收情況,如果發(fā)現(xiàn)有垃圾對(duì)象沒(méi)有被回收,就會(huì)去分析當(dāng)前的內(nèi)存快照,也就是上邊MAT用到的.hprof文件,找到對(duì)象的引用鏈,并顯示在頁(yè)面上。

使用:

在build.gradle文件中添加

在應(yīng)用的application onCreate方法中添加LeakCanary.install(this),如下

應(yīng)用運(yùn)行起來(lái)后,LeakCanary會(huì)自動(dòng)去分析當(dāng)前的內(nèi)存狀態(tài),如果檢測(cè)到泄漏會(huì)發(fā)送到通知欄,點(diǎn)擊通知欄就可以跳轉(zhuǎn)到具體的泄漏分析頁(yè)面。

Tips

就目前使用的結(jié)果來(lái)看,絕大部分泄漏是由于使用單例模式hold住了Activity的引用,比如傳入了context或者將Activity作為listener設(shè)置了進(jìn)去,所以在使用單例模式的時(shí)候要特別注意,還有在Activity生命周期結(jié)束的時(shí)候?qū)⒁恍┳远x監(jiān)聽(tīng)器的Activity引用置空。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容