Android APP 性能優(yōu)化的一些思考(二)
內(nèi)存優(yōu)化
在 Android 系統(tǒng)中有個(gè)垃圾內(nèi)存回收機(jī)制,在虛擬機(jī)層自動(dòng)分配和釋放內(nèi)存,因此不需要在代碼中分配和釋放某一塊內(nèi)存,從應(yīng)用層面上不容易出現(xiàn)內(nèi)存泄漏和內(nèi)存溢出等問題,但是需要內(nèi)存管理。Android 系統(tǒng)在內(nèi)存管理上有一個(gè) Generational Heap Memory 模型,內(nèi)存回收的大部分壓力不需要應(yīng)用層關(guān)心, Generational Heap Memory 有自己一套管理機(jī)制,當(dāng)內(nèi)存達(dá)到一個(gè)閾值時(shí),系統(tǒng)會(huì)根據(jù)不同的規(guī)則自動(dòng)釋放系統(tǒng)認(rèn)為可以釋放的內(nèi)存,也正是因?yàn)?Android 程序把內(nèi)存控制的權(quán)力交給了 Generational Heap Memory,一旦出現(xiàn)內(nèi)存泄漏和溢出方面的問題,排查錯(cuò)誤將會(huì)成為一項(xiàng)異常艱難的工作。除此之外,部分 Android 應(yīng)用開發(fā)人員在開發(fā)過程中并沒有特別關(guān)注內(nèi)存的合理使用,也沒有在內(nèi)存方面做太多的優(yōu)化,當(dāng)應(yīng)用程序同時(shí)運(yùn)行越來越多的任務(wù),加上越來越復(fù)雜的業(yè)務(wù)需求時(shí),完全依賴 Android 的內(nèi)存管理機(jī)制就會(huì)導(dǎo)致一系列性能問題逐漸呈現(xiàn),對(duì)應(yīng)用的穩(wěn)定性和性能帶來不可忽視的影響,因此,解決內(nèi)存問題和合理優(yōu)化內(nèi)存是非常有必要的。
Android內(nèi)存管理機(jī)制
Android 應(yīng)用都是在 Android 的虛擬機(jī)上運(yùn)行,應(yīng)用 程序的內(nèi)存分配與垃圾回收都是由虛擬機(jī)完成的。在 Android 系統(tǒng),虛擬機(jī)有兩種運(yùn)行模式:Dalvik 和 ART。
1、Java對(duì)象生命周期
一般Java對(duì)象在虛擬機(jī)上有7個(gè)運(yùn)行階段:
創(chuàng)建階段->應(yīng)用階段->不可見階段->不可達(dá)階段->收集階段->終結(jié)階段->對(duì)象空間重新分配階段
2、內(nèi)存分配
在 Android 系統(tǒng)中,內(nèi)存分配實(shí)際上是對(duì)堆的分配和釋放。當(dāng)一個(gè) Android 程序啟動(dòng),應(yīng)用進(jìn)程都是從一個(gè)叫做 Zygote 的進(jìn)程衍生出來,系統(tǒng)啟動(dòng) Zygote 進(jìn)程后,為了啟動(dòng)一個(gè)新的應(yīng)用程序進(jìn)程,系統(tǒng)會(huì)衍生 Zygote 進(jìn)程生成一個(gè)新的進(jìn)程,然后在新的進(jìn)程中加載并運(yùn)行應(yīng)用程序的代碼。其中,大多數(shù)的 RAM pages 被用來分配給Framework 代碼,同時(shí)促使 RAM 資源能夠在應(yīng)用所有進(jìn)程之間共享。
但是為了整個(gè)系統(tǒng)的內(nèi)存控制需要,Android 系統(tǒng)會(huì)為每一個(gè)應(yīng)用程序都設(shè)置一個(gè)硬性的 Dalvik Heap Size 最大限制閾值,整個(gè)閾值在不同設(shè)備上會(huì)因?yàn)?RAM 大小不同而有所差異。如果應(yīng)用占用內(nèi)存空間已經(jīng)接近整個(gè)閾值時(shí),再嘗試分配內(nèi)存的話,就很容易引起內(nèi)存溢出的錯(cuò)誤。
3、內(nèi)存回收機(jī)制
我們需要知道的是,在 Java 中內(nèi)存被分為三個(gè)區(qū)域:Young Generation(年輕代)、Old Generation(年老代)、Permanent Generation(持久代)。最近分配的對(duì)象會(huì)存放在 Young Generation 區(qū)域。對(duì)象在某個(gè)時(shí)機(jī)觸發(fā) GC 回收垃圾,而沒有回收的就根據(jù)不同規(guī)則,有可能被移動(dòng)到 Old Generation,最后累積一定時(shí)間在移動(dòng)到 Permanent Generation 區(qū)域。系統(tǒng)會(huì)根據(jù)內(nèi)存中不同的內(nèi)存數(shù)據(jù)類型分別執(zhí)行不同的 GC 操作。GC 通過確定對(duì)象是否被活動(dòng)對(duì)象引用來確定是否收集對(duì)象,進(jìn)而動(dòng)態(tài)回收無任何引用的對(duì)象占據(jù)的內(nèi)存空間。但需要注意的是頻繁的 GC 會(huì)增加應(yīng)用的卡頓情況,影響應(yīng)用的流暢性,因此需要盡量減少系統(tǒng) GC 行為,以便提高應(yīng)用的流暢度,減小卡頓發(fā)生的概率。
內(nèi)存分析工具
做內(nèi)存優(yōu)化前,需要了解當(dāng)前應(yīng)用的內(nèi)存使用現(xiàn)狀,通過現(xiàn)狀去分析哪些數(shù)據(jù)類型有問題,各種類型的分布情況如何,以及在發(fā)現(xiàn)問題后如何發(fā)現(xiàn)是哪些具體對(duì)象導(dǎo)致的,這就需要相關(guān)工具來幫助我們。
1、Memory Monitor
Memory Monitor 是一款使用非常簡單的圖形化工具,可以很好地監(jiān)控系統(tǒng)或應(yīng)用的內(nèi)存使用情況,主要有以下功能:
- 顯示可用和已用內(nèi)存,并且以時(shí)間為維度實(shí)時(shí)反應(yīng)內(nèi)存分配和回收情況。
- 快速判斷應(yīng)用程序的運(yùn)行緩慢是否由于過度的內(nèi)存回收導(dǎo)致。
- 快速判斷應(yīng)用是否由于內(nèi)存不足導(dǎo)致程序崩潰。
2、Heap Viewer
Heap Viewer 的主要功能是查看不同數(shù)據(jù)類型在內(nèi)存中的使用情況,可以看到當(dāng)前進(jìn)程中的 Heap Size 的情況,分別有哪些類型的數(shù)據(jù),以及各種類型數(shù)據(jù)占比情況。通過分析這些數(shù)據(jù)來找到大的內(nèi)存對(duì)象,再進(jìn)一步分析這些大對(duì)象,進(jìn)而通過優(yōu)化減少內(nèi)存開銷,也可以通過數(shù)據(jù)的變化發(fā)現(xiàn)內(nèi)存泄漏。
3、Allocation Tracker
Memory Monitor 和 Heap Viewer 都可以很直觀且實(shí)時(shí)地監(jiān)控內(nèi)存使用情況,還能發(fā)現(xiàn)內(nèi)存問題,但發(fā)現(xiàn)內(nèi)存問題后不能再進(jìn)一步找到原因,或者發(fā)現(xiàn)一塊異常內(nèi)存,但不能區(qū)別是否正常,同時(shí)在發(fā)現(xiàn)問題后,也不能定位到具體的類和方法。這時(shí)就需要使用另一個(gè)內(nèi)存分析工具 Allocation Tracker,進(jìn)行更詳細(xì)的分析, Allocation Tracker 可以分配跟蹤記錄應(yīng)用程序的內(nèi)存分配,并列出了它們的調(diào)用堆棧,可以查看所有對(duì)象內(nèi)存分配的周期。
4、Memory Analyzer Tool(MAT)
MAT 是一個(gè)快速,功能豐富的 Java Heap 分析工具,通過分析 Java 進(jìn)程的內(nèi)存快照 HPROF 分析,從眾多的對(duì)象中分析,快速計(jì)算出在內(nèi)存中對(duì)象占用的大小,查看哪些對(duì)象不能被垃圾收集器回收,并可以通過視圖直觀地查看可能造成這種結(jié)果的對(duì)象。
常見內(nèi)存泄漏場景
如果在內(nèi)存泄漏發(fā)生后再去找原因并修復(fù)會(huì)增加開發(fā)的成本,最好在編寫代碼時(shí)就能夠很好地考慮內(nèi)存問題,寫出更高質(zhì)量的代碼,這里列出一些常見的內(nèi)存泄漏場景,在以后的開發(fā)過程中需要避免這類問題。
- 資源性對(duì)象未關(guān)閉。比如Cursor、File文件等,往往都用了一些緩沖,在不使用時(shí),應(yīng)該及時(shí)關(guān)閉它們。
- 注冊(cè)對(duì)象未注銷。比如事件注冊(cè)后未注銷,會(huì)導(dǎo)致觀察者列表中維持著對(duì)象的引用。
- 類的靜態(tài)變量持有大數(shù)據(jù)對(duì)象。
- 非靜態(tài)內(nèi)部類的靜態(tài)實(shí)例。
- Handler臨時(shí)性內(nèi)存泄漏。如果Handler是非靜態(tài)的,容易導(dǎo)致 Activity 或 Service 不會(huì)被回收。
- 容器中的對(duì)象沒清理造成的內(nèi)存泄漏。
- WebView。WebView 存在著內(nèi)存泄漏的問題,在應(yīng)用中只要使用一次 WebView,內(nèi)存就不會(huì)被釋放掉。
除此之外,內(nèi)存泄漏可監(jiān)控,常見的就是用LeakCanary 第三方庫,這是一個(gè)檢測內(nèi)存泄漏的開源庫,使用非常簡單,可以在發(fā)生內(nèi)存泄漏時(shí)告警,并且生成 leak tarce 分析泄漏位置,同時(shí)可以提供 Dump 文件進(jìn)行分析。
優(yōu)化內(nèi)存空間
沒有內(nèi)存泄漏,并不意味著內(nèi)存就不需要優(yōu)化,在移動(dòng)設(shè)備上,由于物理設(shè)備的存儲(chǔ)空間有限,Android 系統(tǒng)對(duì)每個(gè)應(yīng)用進(jìn)程也都分配了有限的堆內(nèi)存,因此使用最小內(nèi)存對(duì)象或者資源可以減小內(nèi)存開銷,同時(shí)讓GC 能更高效地回收不再需要使用的對(duì)象,讓應(yīng)用堆內(nèi)存保持充足的可用內(nèi)存,使應(yīng)用更穩(wěn)定高效地運(yùn)行。
常見做法如下:
- 對(duì)象引用。強(qiáng)引用、軟引用、弱引用、虛引用四種引用類型,根據(jù)業(yè)務(wù)需求合理使用不同,選擇不同的引用類型。
- 減少不必要的內(nèi)存開銷。注意自動(dòng)裝箱,增加內(nèi)存復(fù)用,比如有效利用系統(tǒng)自帶的資源、視圖復(fù)用、對(duì)象池、Bitmap對(duì)象的復(fù)用。
- 使用最優(yōu)的數(shù)據(jù)類型。比如針對(duì)數(shù)據(jù)類容器結(jié)構(gòu),可以使用ArrayMap數(shù)據(jù)結(jié)構(gòu),避免使用枚舉類型,使用緩存Lrucache等等。
- 圖片內(nèi)存優(yōu)化??梢栽O(shè)置位圖規(guī)格,根據(jù)采樣因子做壓縮,用一些圖片緩存方式對(duì)圖片進(jìn)行管理等等。

責(zé)任編輯:售電衡衡
-
權(quán)威發(fā)布 | 新能源汽車產(chǎn)業(yè)頂層設(shè)計(jì)落地:鼓勵(lì)“光儲(chǔ)充放”,有序推進(jìn)氫燃料供給體系建設(shè)
2020-11-03新能源,汽車,產(chǎn)業(yè),設(shè)計(jì) -
中國自主研制的“人造太陽”重力支撐設(shè)備正式啟運(yùn)
2020-09-14核聚變,ITER,核電 -
探索 | 既耗能又可供能的數(shù)據(jù)中心 打造融合型綜合能源系統(tǒng)
2020-06-16綜合能源服務(wù),新能源消納,能源互聯(lián)網(wǎng)
-
新基建助推 數(shù)據(jù)中心建設(shè)將迎爆發(fā)期
2020-06-16數(shù)據(jù)中心,能源互聯(lián)網(wǎng),電力新基建 -
泛在電力物聯(lián)網(wǎng)建設(shè)下看電網(wǎng)企業(yè)數(shù)據(jù)變現(xiàn)之路
2019-11-12泛在電力物聯(lián)網(wǎng) -
泛在電力物聯(lián)網(wǎng)建設(shè)典型實(shí)踐案例
2019-10-15泛在電力物聯(lián)網(wǎng)案例
-
新基建之充電樁“火”了 想進(jìn)這個(gè)行業(yè)要“心里有底”
2020-06-16充電樁,充電基礎(chǔ)設(shè)施,電力新基建 -
燃料電池汽車駛?cè)雽こ0傩占疫€要多久?
-
備戰(zhàn)全面電動(dòng)化 多部委及央企“定調(diào)”充電樁配套節(jié)奏
-
權(quán)威發(fā)布 | 新能源汽車產(chǎn)業(yè)頂層設(shè)計(jì)落地:鼓勵(lì)“光儲(chǔ)充放”,有序推進(jìn)氫燃料供給體系建設(shè)
2020-11-03新能源,汽車,產(chǎn)業(yè),設(shè)計(jì) -
中國自主研制的“人造太陽”重力支撐設(shè)備正式啟運(yùn)
2020-09-14核聚變,ITER,核電 -
能源革命和電改政策紅利將長期助力儲(chǔ)能行業(yè)發(fā)展
-
探索 | 既耗能又可供能的數(shù)據(jù)中心 打造融合型綜合能源系統(tǒng)
2020-06-16綜合能源服務(wù),新能源消納,能源互聯(lián)網(wǎng) -
5G新基建助力智能電網(wǎng)發(fā)展
2020-06-125G,智能電網(wǎng),配電網(wǎng) -
從智能電網(wǎng)到智能城市
-
山西省首座電力與通信共享電力鐵塔試點(diǎn)成功
-
中國電建公司公共資源交易服務(wù)平臺(tái)摘得電力創(chuàng)新大獎(jiǎng)
-
電力系統(tǒng)對(duì)UPS的技術(shù)要求