1. 為什么需要熱修復技術
當我們的Android應用程序發(fā)布到各大市場上之后,如果出現(xiàn)了重大bug,大部分情況下只能通過緊急發(fā)包升級來解決問題,但是這會帶來以下幾個問題:
- 應用升級需要一定的時間,時效性差,如iOS應用發(fā)布審核可能需要好幾天;
- 需要用戶下載更新安裝包,如果不是強制升級,用戶可能不會選擇升級,而強制升級會導致用戶體驗急劇下降,從而引起更多用戶的流失;
- 如果是緊急重大bug,并且是發(fā)生在客戶端的,我們無法控制用戶手上的應用程序,無法采取任何有效的應急措施,可能造成不可挽回的損失;
當我們的Android應用程序采取了熱修復技術之后,當發(fā)生上述情況時,及時更新上傳熱修復補丁包,能在用戶無感知的情況下修復bug,這聽起來是不是很完美。目前市面上的Android熱修復技術很多,各個大廠都有自己成熟的熱修復技術方案,我在這里并不是想重新造個輪子,而是逐步探究熱修復技術的實現(xiàn)原理,這樣在談到熱修復時能夠做到游刃有余。實際上,它并沒有我們想想中的那么高深莫測。
2. Android熱修復的基石-虛擬機
Java應用程序是由Java虛擬機啟動加載的,Android應用程序則是由Android虛擬機啟動加載的,要了解熱修復的原理,我們必須要對Android虛擬機有所了解。
通常在Java平臺上我們采用的Java虛擬機,能夠加載識別符合java規(guī)范的class文件或二進制字節(jié)流。在Android平臺上,雖然應用程序也是采用java來編寫的,但是它采用了與Java平臺不同的虛擬機實現(xiàn)方案,通常它并不直接加載class文件,而是加載由一系列class文件組合而成的dex文件。
Android發(fā)展至今,虛擬機從最早的Dalvik虛擬機到現(xiàn)在的Art虛擬機,經歷過多次優(yōu)化,我們先總體了解下每個虛擬機的特點以及差別。
3. Dalvik虛擬機
Dalvik是Google公司自己設計用于Android平臺的虛擬機。Dalvik虛擬機是Google等廠商合作開發(fā)的Android移動設備平臺的核心組成部分之一。它可以支持已轉換為 .dex(即Dalvik Executable)格式的Java應用程序的運行,.dex格式是專為Dalvik設計的一種壓縮格式,適合內存和處理器速度有限的系統(tǒng)。Dalvik 經過優(yōu)化,允許在有限的內存中同時運行多個虛擬機的實例,并且每一個Dalvik 應用作為一個獨立的Linux 進程執(zhí)行。獨立的進程可以防止在虛擬機崩潰的時候所有程序都被關閉。
這是百度百科里對Dalvik虛擬機的介紹,點擊這里百度百科Dalvik可以查看具體介紹。
那么Dalvik與標準的JVM相比有什么特點呢,從百度百科里可以看到以下相關資料:
- 首要差別是Dalvik基于寄存器,JVM基于棧;
- Dalvik負責進程隔離和線程管理,每一個Android應用在底層都會對應一個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以執(zhí)行;
- Dalvik運行的是其專有的文件格式dex,而JVM運行的是java字節(jié)碼;
- dex文件格式可以減少整體文件大小,提高I/O操作的類查找速度;
- odex是為了在運行過程中進一步提高性能,對dex文件的進一步優(yōu)化;
- 為簡化翻譯,常量池只使用32位索引;
基于寄存器與基于棧的虛擬機有什么不同,本人也只懂皮毛,不在這里討論了。我們可以看到,Dalvik虛擬機運行的是dex文件。.dex文件是Google創(chuàng)造的一種文件格式,它是由多個Java的.class文件轉換而成,一個.dex文件包含了多個Java的.class文件信息。為了節(jié)省空間,.dex文件共用了很多類名稱、常量字符串等,由同樣的java代碼編譯而成的.dex文件與.jar文件相比,.dex文件體積會小很多。
Android應用打包成apk文件的過程為:將java文件編譯后得到.class文件,.class文件通過dex轉換工具編譯成.dex文件,最后將資源文件和.dex文件打包成.apk文件。
4. ART虛擬機
在Android5.0及后續(xù)版本中,Google采用了ART正式取代了以往的Dalvik虛擬機。ART與Dalvik的主要區(qū)別有:
4.1 ART采用AOT技術替代了JIT
我們先了解下JIT與AOT這兩個名詞術語:
- JIT:Just In Time,及時編譯技術。JIT會在運行時分析應用程序的代碼,識別哪些方法可以歸類為熱方法,這些方法會被JIT編譯器編譯成對應的匯編代碼,然后存儲到代碼緩存中,以后調用這些代碼時就不用解釋執(zhí)行了,可以直接使用代碼緩存中已編譯好的匯編代碼,能顯著提升應用程序的執(zhí)行效率。
- AOT:Ahead Of Time,預編譯技術。編譯器在編譯時直接將源程序編譯成目標機器碼,運行時直接運行機器碼。
Dalvik采用的是JIT技術,而ART采用的是AOT技術。ART在應用程序安裝的時候,就已經將所有的字節(jié)碼編譯成了機器碼,運行的時候直接運行的是機器碼。而Dalvik則是在應用程序運行的時候,實時將字節(jié)碼編譯成機器碼。因此,ART與Dalivk相比,省去了運行時將字節(jié)碼編譯成機器碼的過程,極大地提升了應用程序的運行效率。
雖然運行效率有了提升,但同時帶來了其他缺點:
- 安裝時需要將字節(jié)碼編譯成機器碼,因此ART需要更大的存儲空間;
- 安裝需要花更多的時間;
可以說,這是一個以空間換時間的策略,但是在存儲設備越來越便宜的今天,以空間換時間應該是一個比較劃算的方式。
4.2 提搞了垃圾回收效率
Dalvik在gc時,會掛起虛擬機內部的所有線程,然后gc查找所有可回收的對象進行回收,回收完成后恢復所有掛起的線程。需要注意的是,gc與應用程序的運行并不是并發(fā)執(zhí)行的,發(fā)生gc時就會出現(xiàn)平常我們所說的Stop The World現(xiàn)象,應用程序如同停止了一樣,如果gc頻繁或者gc時間過長都會導致應用程序運行卡頓。
ART對gc做了一定的改善,Dalivk的gc操作與應用程序是同時執(zhí)行的(非并發(fā)),而ART則將原來的非并發(fā)過程改成了部分并發(fā),縮短了gc時間,提升了垃圾回收的效率。
4.3 提高了內存使用率、減少了內存碎片化
Dalvik虛擬機垃圾回收采用了Mark and Sweep算法,即“標記-清除”算法,這種算法先對需要回收的內存區(qū)域進行標記,然后再統(tǒng)一清除,它是一種比較
高效的算法,但是帶來的弊端是會造成可用內存塊的不連續(xù),碎片化嚴重。虛擬機多次gc之后,本來連續(xù)的內存區(qū)域變得千瘡百孔,以后為對象分配內存尋址會越來越難。
而ART在內存分配上做了優(yōu)化,比如它開辟了一塊名為Large Object Space的內存區(qū)域,專門用來存放大對象,同時還引入了一個名為moving collector的技術,專門用來將gc后不連續(xù)的物理內存塊對其,解決了Dalvik上內存碎片化嚴重的問題。
5. 小結
本文只是對Dalvik與ART做了一個初步的介紹,先明白一個大概原理,這樣才能逐步理解熱修復的過程。