Android熱修復(fù)技術(shù)初探(一):了解Dalvik與Art虛擬機(jī)

1. 為什么需要熱修復(fù)技術(shù)

當(dāng)我們的Android應(yīng)用程序發(fā)布到各大市場(chǎng)上之后,如果出現(xiàn)了重大bug,大部分情況下只能通過(guò)緊急發(fā)包升級(jí)來(lái)解決問(wèn)題,但是這會(huì)帶來(lái)以下幾個(gè)問(wèn)題:

  1. 應(yīng)用升級(jí)需要一定的時(shí)間,時(shí)效性差,如iOS應(yīng)用發(fā)布審核可能需要好幾天;
  2. 需要用戶下載更新安裝包,如果不是強(qiáng)制升級(jí),用戶可能不會(huì)選擇升級(jí),而強(qiáng)制升級(jí)會(huì)導(dǎo)致用戶體驗(yàn)急劇下降,從而引起更多用戶的流失;
  3. 如果是緊急重大bug,并且是發(fā)生在客戶端的,我們無(wú)法控制用戶手上的應(yīng)用程序,無(wú)法采取任何有效的應(yīng)急措施,可能造成不可挽回的損失;

當(dāng)我們的Android應(yīng)用程序采取了熱修復(fù)技術(shù)之后,當(dāng)發(fā)生上述情況時(shí),及時(shí)更新上傳熱修復(fù)補(bǔ)丁包,能在用戶無(wú)感知的情況下修復(fù)bug,這聽(tīng)起來(lái)是不是很完美。目前市面上的Android熱修復(fù)技術(shù)很多,各個(gè)大廠都有自己成熟的熱修復(fù)技術(shù)方案,我在這里并不是想重新造個(gè)輪子,而是逐步探究熱修復(fù)技術(shù)的實(shí)現(xiàn)原理,這樣在談到熱修復(fù)時(shí)能夠做到游刃有余。實(shí)際上,它并沒(méi)有我們想想中的那么高深莫測(cè)。

2. Android熱修復(fù)的基石-虛擬機(jī)

Java應(yīng)用程序是由Java虛擬機(jī)啟動(dòng)加載的,Android應(yīng)用程序則是由Android虛擬機(jī)啟動(dòng)加載的,要了解熱修復(fù)的原理,我們必須要對(duì)Android虛擬機(jī)有所了解。

通常在Java平臺(tái)上我們采用的Java虛擬機(jī),能夠加載識(shí)別符合java規(guī)范的class文件或二進(jìn)制字節(jié)流。在Android平臺(tái)上,雖然應(yīng)用程序也是采用java來(lái)編寫的,但是它采用了與Java平臺(tái)不同的虛擬機(jī)實(shí)現(xiàn)方案,通常它并不直接加載class文件,而是加載由一系列class文件組合而成的dex文件。

Android發(fā)展至今,虛擬機(jī)從最早的Dalvik虛擬機(jī)到現(xiàn)在的Art虛擬機(jī),經(jīng)歷過(guò)多次優(yōu)化,我們先總體了解下每個(gè)虛擬機(jī)的特點(diǎn)以及差別。

3. Dalvik虛擬機(jī)

Dalvik是Google公司自己設(shè)計(jì)用于Android平臺(tái)的虛擬機(jī)。Dalvik虛擬機(jī)是Google等廠商合作開發(fā)的Android移動(dòng)設(shè)備平臺(tái)的核心組成部分之一。它可以支持已轉(zhuǎn)換為 .dex(即Dalvik Executable)格式的Java應(yīng)用程序的運(yùn)行,.dex格式是專為Dalvik設(shè)計(jì)的一種壓縮格式,適合內(nèi)存和處理器速度有限的系統(tǒng)。Dalvik 經(jīng)過(guò)優(yōu)化,允許在有限的內(nèi)存中同時(shí)運(yùn)行多個(gè)虛擬機(jī)的實(shí)例,并且每一個(gè)Dalvik 應(yīng)用作為一個(gè)獨(dú)立的Linux 進(jìn)程執(zhí)行。獨(dú)立的進(jìn)程可以防止在虛擬機(jī)崩潰的時(shí)候所有程序都被關(guān)閉。

這是百度百科里對(duì)Dalvik虛擬機(jī)的介紹,點(diǎn)擊這里百度百科Dalvik可以查看具體介紹。

那么Dalvik與標(biāo)準(zhǔn)的JVM相比有什么特點(diǎn)呢,從百度百科里可以看到以下相關(guān)資料:

  1. 首要差別是Dalvik基于寄存器,JVM基于棧;
  2. Dalvik負(fù)責(zé)進(jìn)程隔離和線程管理,每一個(gè)Android應(yīng)用在底層都會(huì)對(duì)應(yīng)一個(gè)獨(dú)立的Dalvik虛擬機(jī)實(shí)例,其代碼在虛擬機(jī)的解釋下得以執(zhí)行;
  3. Dalvik運(yùn)行的是其專有的文件格式dex,而JVM運(yùn)行的是java字節(jié)碼;
  4. dex文件格式可以減少整體文件大小,提高I/O操作的類查找速度;
  5. odex是為了在運(yùn)行過(guò)程中進(jìn)一步提高性能,對(duì)dex文件的進(jìn)一步優(yōu)化;
  6. 為簡(jiǎn)化翻譯,常量池只使用32位索引;

基于寄存器與基于棧的虛擬機(jī)有什么不同,本人也只懂皮毛,不在這里討論了。我們可以看到,Dalvik虛擬機(jī)運(yùn)行的是dex文件。.dex文件是Google創(chuàng)造的一種文件格式,它是由多個(gè)Java的.class文件轉(zhuǎn)換而成,一個(gè).dex文件包含了多個(gè)Java的.class文件信息。為了節(jié)省空間,.dex文件共用了很多類名稱、常量字符串等,由同樣的java代碼編譯而成的.dex文件與.jar文件相比,.dex文件體積會(huì)小很多。

Android應(yīng)用打包成apk文件的過(guò)程為:將java文件編譯后得到.class文件,.class文件通過(guò)dex轉(zhuǎn)換工具編譯成.dex文件,最后將資源文件和.dex文件打包成.apk文件。

4. ART虛擬機(jī)

在Android5.0及后續(xù)版本中,Google采用了ART正式取代了以往的Dalvik虛擬機(jī)。ART與Dalvik的主要區(qū)別有:

4.1 ART采用AOT技術(shù)替代了JIT

我們先了解下JIT與AOT這兩個(gè)名詞術(shù)語(yǔ):

  • JIT:Just In Time,及時(shí)編譯技術(shù)。JIT會(huì)在運(yùn)行時(shí)分析應(yīng)用程序的代碼,識(shí)別哪些方法可以歸類為熱方法,這些方法會(huì)被JIT編譯器編譯成對(duì)應(yīng)的匯編代碼,然后存儲(chǔ)到代碼緩存中,以后調(diào)用這些代碼時(shí)就不用解釋執(zhí)行了,可以直接使用代碼緩存中已編譯好的匯編代碼,能顯著提升應(yīng)用程序的執(zhí)行效率。
  • AOT:Ahead Of Time,預(yù)編譯技術(shù)。編譯器在編譯時(shí)直接將源程序編譯成目標(biāo)機(jī)器碼,運(yùn)行時(shí)直接運(yùn)行機(jī)器碼。

Dalvik采用的是JIT技術(shù),而ART采用的是AOT技術(shù)。ART在應(yīng)用程序安裝的時(shí)候,就已經(jīng)將所有的字節(jié)碼編譯成了機(jī)器碼,運(yùn)行的時(shí)候直接運(yùn)行的是機(jī)器碼。而Dalvik則是在應(yīng)用程序運(yùn)行的時(shí)候,實(shí)時(shí)將字節(jié)碼編譯成機(jī)器碼。因此,ART與Dalivk相比,省去了運(yùn)行時(shí)將字節(jié)碼編譯成機(jī)器碼的過(guò)程,極大地提升了應(yīng)用程序的運(yùn)行效率。

雖然運(yùn)行效率有了提升,但同時(shí)帶來(lái)了其他缺點(diǎn):

  • 安裝時(shí)需要將字節(jié)碼編譯成機(jī)器碼,因此ART需要更大的存儲(chǔ)空間;
  • 安裝需要花更多的時(shí)間;

可以說(shuō),這是一個(gè)以空間換時(shí)間的策略,但是在存儲(chǔ)設(shè)備越來(lái)越便宜的今天,以空間換時(shí)間應(yīng)該是一個(gè)比較劃算的方式。

4.2 提搞了垃圾回收效率

Dalvik在gc時(shí),會(huì)掛起虛擬機(jī)內(nèi)部的所有線程,然后gc查找所有可回收的對(duì)象進(jìn)行回收,回收完成后恢復(fù)所有掛起的線程。需要注意的是,gc與應(yīng)用程序的運(yùn)行并不是并發(fā)執(zhí)行的,發(fā)生gc時(shí)就會(huì)出現(xiàn)平常我們所說(shuō)的Stop The World現(xiàn)象,應(yīng)用程序如同停止了一樣,如果gc頻繁或者gc時(shí)間過(guò)長(zhǎng)都會(huì)導(dǎo)致應(yīng)用程序運(yùn)行卡頓。

ART對(duì)gc做了一定的改善,Dalivk的gc操作與應(yīng)用程序是同時(shí)執(zhí)行的(非并發(fā)),而ART則將原來(lái)的非并發(fā)過(guò)程改成了部分并發(fā),縮短了gc時(shí)間,提升了垃圾回收的效率。

4.3 提高了內(nèi)存使用率、減少了內(nèi)存碎片化

Dalvik虛擬機(jī)垃圾回收采用了Mark and Sweep算法,即“標(biāo)記-清除”算法,這種算法先對(duì)需要回收的內(nèi)存區(qū)域進(jìn)行標(biāo)記,然后再統(tǒng)一清除,它是一種比較
高效的算法,但是帶來(lái)的弊端是會(huì)造成可用內(nèi)存塊的不連續(xù),碎片化嚴(yán)重。虛擬機(jī)多次gc之后,本來(lái)連續(xù)的內(nèi)存區(qū)域變得千瘡百孔,以后為對(duì)象分配內(nèi)存尋址會(huì)越來(lái)越難。

而ART在內(nèi)存分配上做了優(yōu)化,比如它開辟了一塊名為Large Object Space的內(nèi)存區(qū)域,專門用來(lái)存放大對(duì)象,同時(shí)還引入了一個(gè)名為moving collector的技術(shù),專門用來(lái)將gc后不連續(xù)的物理內(nèi)存塊對(duì)其,解決了Dalvik上內(nèi)存碎片化嚴(yán)重的問(wèn)題。

5. 小結(jié)

本文只是對(duì)Dalvik與ART做了一個(gè)初步的介紹,先明白一個(gè)大概原理,這樣才能逐步理解熱修復(fù)的過(guò)程。

參考文章

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容