相關文章
Android性能優化系列
Java虛擬機系列html
要學習Android的內存優化,首先要了解Java虛擬機,此前我用了多篇文章來介紹Java虛擬機的知識,就是爲了這個系列作鋪墊。在Android開發中咱們接觸的是與Java虛擬機相似的Dalvik虛擬機和ART虛擬機,這一篇咱們就來了解它們的基本原理。java
Dalvik虛擬機( Dalvik Virtual Machine ),簡稱Dalvik VM或者DVM。它是由Dan Bornstein編寫的,名字源於他的祖先居住過的名爲Dalvik的小漁村。DVM是Google專門爲Android平臺開發的虛擬機,它運行在Android運行時庫中。須要注意的是DVM並非一個Java虛擬機(如下簡稱JVM),至於爲何,下文會給你答案。算法
DVM之因此不是一個JVM ,主要緣由是DVM並無遵循JVM規範來實現。DVM與JVM主要有如下區別。性能優化
基於的架構不一樣
JVM基於棧則意味着須要去棧中讀寫數據,所需的指令會更多,這樣會致使速度慢,對於性能有限的移動設備,顯然不是很適合。
DVM是基於寄存器的,它沒有基於棧的虛擬機在拷貝數據而使用的大量的出入棧指令,同時指令更緊湊更簡潔。可是因爲顯示指定了操做數,因此基於寄存器的指令會比基於棧的指令要大,可是因爲指令數量的減小,總的代碼數不會增長多少。微信
執行的字節碼不一樣
在Java SE程序中,Java類會被編譯成一個或多個.class文件,打包成jar文件,然後JVM會經過相應的.class文件和jar文件獲取相應的字節碼。執行順序爲: .java文件 -> .class文件 -> .jar文件
而DVM會用dx工具將全部的.class文件轉換爲一個.dex文件,而後DVM會從該.dex文件讀取指令和數據。執行順序爲:
.java文件 –>.class文件-> .dex文件
數據結構
如上圖所示,.jar文件裏面包含多個.class文件,每一個.class文件裏面包含了該類的常量池、類信息、屬性等等。當JVM加載該.jar文件的時候,會加載裏面的全部的.class文件,JVM的這種加載方式很慢,對於內存有限的移動設備並不合適。
而在.apk文件中只包含了一個.dex文件,這個.dex文件裏面將全部的.class裏面所包含的信息所有整合在一塊兒了,這樣再加載就提升了速度。.class文件存在不少的冗餘信息,dex工具會去除冗餘信息,並把全部的.class文件整合到.dex文件中,減小了I/O操做,提升了類的查找速度。架構
DVM容許在有限的內存中同時運行多個進程
DVM通過優化,容許在有限的內存中同時運行多個進程。在Android中的每個應用都運行在一個DVM實例中,每個DVM實例都運行在一個獨立的進程空間。獨立的進程能夠防止在虛擬機崩潰的時候全部程序都被關閉。jvm
DVM由Zygote建立和初始化
在Android系統啓動流程(二)解析Zygote進程啓動過程這篇文章中我介紹過 Zygote,能夠稱它爲孵化器,它是一個DVM進程,同時它也用來建立和初始化DVM實例。每當系統須要建立一個應用程序時,Zygote就會fock自身,快速的建立和初始化一個DVM實例,用於應用程序的運行。工具
DVM的源碼位於dalvik/目錄下,其中dalvik/vm目錄下的內容是DVM的具體實現部分,它會被編譯成libdvm.so;dalvik/libdex會被編譯成libdex.a靜態庫,做爲dex工具使用;dalvik/dexdump是.dex文件的反編譯工具;DVM的可執行程序位於dalvik/dalvikvm中,將會被編譯成dalvikvm可執行程序。DVM架構以下圖所示。性能
DVM的運行時堆主要由兩個Space以及多個輔助數據結構組成,兩個Space分別是Zygote Space(Zygote Heap)和Allocation Space(Active Heap)。Zygote Space用來管理Zygote進程在啓動過程當中預加載和建立的各類對象,Zygote Space中不會觸發GC,全部進程都共享該區域,好比系統資源。Allocation Space是在Zygote進程fork第一個子進程以前建立的,它是一種私有進程,Zygote進程和fock的子進程在Allocation Space上進行對象分配和釋放。
除了這兩個Space,還包含如下數據結構:
ART(Android Runtime)是Android 4.4發佈的,用來替換Dalvik虛擬,Android 4.4默認採用的仍是DVM,系統會提供一個選項來開啓ART。在Android 5.0時,默認採用ART,DVM今後退出歷史舞臺。
DVM中的應用每次運行時,字節碼都須要經過即時編譯器(JIT,just in time)轉換爲機器碼,這會使得應用的運行效率下降。而在ART中,系統在安裝應用時會進行一次預編譯(AOT,ahead of time),將字節碼預先編譯成機器碼並存儲在本地,這樣應用每次運行時就不須要執行編譯了,運行效率也大大提高。
與DVM的GC不一樣的是,ART的GC類型有多種,主要分爲Mark-Sweep GC和Compacting GC。ART的運行時堆的空間根據不一樣的GC類型也有着不一樣的劃分,若是採用的是Mark-Sweep GC,運行時堆主要是由四個Space和多個輔助數據結構組成,四個Space分別是Zygote Space、Allocation Space、Image Space和Large Object Space。Zygote Space、Allocation Space和DVM中的做用是同樣的。Image Space用來存放一些預加載類,Large Object Space用來分配一些大對象(默認大小爲12k)。其中Zygote Space和Image Space是進程間共享的。
採用Mark-Sweep GC的運行時堆空間劃分以下圖所示。
除了這四個Space,ART的Java堆中還包括兩個Mod Union Table,一個Card Table,兩個Heap Bitmap,兩個Object Map,以及三個Object Stack。若是想要跟多的瞭解它們,請參考ART運行時Java堆建立過程分析 -- 羅昇陽這篇文章。
參考資料
《深刻解析Android虛擬機》
《Android技術內幕-系統卷》
《Android性能優化最佳實踐》
stackoverflow:關於dvm存儲的問題
Dalvik Virtual Machine -- COSC 530
ART運行時Java堆建立過程分析 -- 羅昇陽
Dalvik虛擬機Java堆建立過程分析 -- 羅昇陽
ART運行時垃圾收集機制簡要介紹和學習計劃 -- 羅昇陽
Android 性能優化—Android memory 參數tuning(二)
歡迎關注個人微信公衆號,第一時間得到博客更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,便可關注。