[原文出處-----Dalvik虛擬機簡要介紹和學習計劃](http://blog.csdn.net/luoshengyang/article/details/8852432)
我們知道,Android應用程序是運行在Dalvik虛擬機里面的,并且每一個應用程序對應有一個單獨的Dalvik虛擬機實例。除了指令集和類文件格式不同,Dalvik虛擬機與Java虛擬機共享有差不多的特性,例如,它們都是解釋執行,并且支持即時編譯(JIT)、垃圾收集(GC)、Java本地方法調用(JNI)和Java遠程調試協議(JDWP)等。本文對Dalvik虛擬機進行簡要介紹,以及制定學習計劃。
Dalvik虛擬機是由[Dan Bornstein](http://www.milk.com/home/danfuzz/)開發的,名字來源于他的祖先曾經居住過的位于冰島的同名小漁村。Dalvik虛擬機起源于[Apache Harmony](http://zh.wikipedia.org/wiki/Apache_Harmony)項目,后者是由Apache軟件基金會主導的,目標是實現一個獨立的、兼容JDK 5的虛擬機,并根據Apache License v2發布。由此可見,Dalvik虛擬機從誕生的那一天開始,就和Java有說不清理不斷的關系。
Dalvik虛擬機與Java虛擬機的最顯著區別是它們分別具有不同的類文件格式以及指令集。Dalvik虛擬機使用的是dex(Dalvik Executable)格式的類文件,而Java虛擬機使用的是class格式的類文件。一個dex文件可以包含若干個類,而一個class文件只包括一個類。由于一個dex文件可以包含若干個類,因此它就可以將各個類中重復的字符串和其它常數只保存一次,從而節省了空間,這樣就適合在內存和處理器速度有限的手機系統中使用。一般來說,包含有相同類的未壓縮dex文件稍小于一個已經壓縮的jar文件。
Dalvik虛擬機使用的指令是基于寄存器的,而Java虛擬機使用的指令集是基于堆棧的。基于堆棧的指令很緊湊,例如,Java虛擬機使用的指令只占一個字節,因而稱為字節碼。基于寄存器的指令由于需要指定源地址和目標地址,因此需要占用更多的指令空間,例如,Dalvik虛擬機的某些指令需要占用兩個字節。基于堆棧和基于寄存器的指令集各有優劣,一般而言,執行同樣的功能,前者需要更多的指令(主要是load和store指令),而后者需要更多的指令空間。需要更多指令意味著要多占用CPU時間,而需要更多指令空間意味著數據緩沖(d-cache)更易失效。
此外,還有一種觀點認為,基于堆棧的指令更具可移植性,因為它不對目標機器的寄存器進行任何假設。然而,基于寄存器的指令由于對目標機器的寄存器進行了假設,因此,它更有利于進行[AOT](http://en.wikipedia.org/wiki/AOT_compiler)(ahead-of-time)優化。 所謂AOT,就是在解釋語言程序運行之前,就先將它編譯成本地機器語言程序。AOT本質上是一種靜態編譯,它是相對于JIT而言的,也就是說,前者是在程序運行前進行編譯,而后者是在程序運行時進行編譯。運行時編譯意味著可以利用運行時信息來得到比較靜態編譯更優化的代碼,同時也意味不能進行某些高級優化,因為優化過程太耗時了。另一方面,運行前編譯由于不占用程序運行時間,因此,它就可以不計時間成本來優化代碼。無論AOT,還是JIT,最終的目標都是將解釋語言編譯為本地機器語言,而本地機器語言都是基于寄存器來執行的,因此,在某種程度來講,基于寄存器的指令更有利于進行AOT編譯以及優化。
事實上,基于寄存器和基于堆棧的指令集之爭,就如精簡指令集(RISC)和復雜指令集(CISC)之爭,誰優誰劣,至今是沒有定論的。例如,上面提到完成相同的功能,基于堆棧的Java虛擬機需要更多的指令,因此就會比基于寄存器的Dalvik虛擬機慢,然而,在2010年,Oracle在一個ARM設備上使用一個non-graphical Java benchmarks來對比Java SE Embedded和Android 2.2的性能,發現后者比前者慢了2~3倍。上述性能比較結論以及數據可以參考以下兩篇文章:
1. [Virtual Machine Showdown: Stack Versus Registers](http://static.usenix.org/events/vee05/full_papers/p153-yunhe.pdf)
2. [Java SE Embedded Performance Versus Android 2.2](https://blogs.oracle.com/javaseembedded/entry/how_does_android_22s_performance_stack_up_against_java_se_embedded)
基于寄存器的Dalvik虛擬機和基于堆棧的Java虛擬機的更多比較和分析,還可以參考以下文章:
1. [維基百科---Dalvik (software)](http://en.wikipedia.org/wiki/Dalvik_(software))
2. [Dalvik, Android's virtual machine, generates significant debate](http://www.infoq.com/news/2007/11/dalvik)
3. [Dalvik 虛擬機和 Sun JVM 在架構和執行方面有什么本質區別?](http://www.zhihu.com/question/20207106)
不管結論如何,Dalvik虛擬機都在盡最大的努力來優化自身,這些措施包括:
1. 將多個類文件收集到同一個dex文件中,以便節省空間;
2. 使用只讀的內存映射方式加載dex文件,以便可以多進程共享dex文件,節省程序加載時間;
3. 提前調整好字節序(byte order)和字對齊(word alignment)方式,使得它們更適合于本地機器,以便提高指令執行速度;
4. 盡量提前進行字節碼驗證(bytecode verification),提高程序的加載速度;
5. 需要重寫字節碼的優化要提前進行。
這些優化措施的更具體描述可以參考[Dalvik Optimization and Verification With dexopt](http://blog.csdn.net/luoshengyang/article/details/8852432)一文。
分析完Dalvik虛擬機和Java虛擬機的區別之后,接下來我們再簡要分析一下Dalvik虛擬機的其它特性,包括內存管理、垃圾收集、JIT、JNI以及進程和線程管理。
一. 內存管理
Dalvik虛擬機的內存大體上可以分為Java Object Heap、Bitmap Memory和Native Heap三種。
Java Object Heap是用來分配Java對象的,也就是我們在代碼new出來的對象都是位于Java Object Heap上的。Dalvik虛擬機在啟動的時候,可以通過-Xms和-Xmx選項來指定Java Object Heap的最小值和最大值。為了避免Dalvik虛擬機在運行的過程中對Java Object Heap的大小進行調整而影響性能,我們可以通過-Xms和-Xmx選項來將它的最小值和最大值設置為相等。
Java Object Heap的最小和最大默認值為2M和16M,但是手機在出廠時,廠商會根據手機的配置情況來對其進行調整,例如,G1、Droid、Nexus One和Xoom的Java Object Heap的最大值分別為16M、24M、32M 和48M。我們可以通過ActivityManager類的成員函數getMemoryClass來獲得Dalvik虛擬機的Java Object Heap的最大值。
ActivityManager類的成員函數getMemoryClass的實現如下所示:
~~~
public class ActivityManager {
......
/**
* Return the approximate per-application memory class of the current
* device. This gives you an idea of how hard a memory limit you should
* impose on your application to let the overall system work best. The
* returned value is in megabytes; the baseline Android memory class is
* 16 (which happens to be the Java heap limit of those devices); some
* device with more memory may return 24 or even higher numbers.
*/
public int getMemoryClass() {
return staticGetMemoryClass();
}
/** @hide */
static public int staticGetMemoryClass() {
// Really brain dead right now -- just take this from the configured
// vm heap size, and assume it is in megabytes and thus ends with "m".
String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");
return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
}
......
}
~~~
這個函數定義在文件frameworks/base/core/java/android/app/ActivityManager.java中。
Dalvik虛擬機在啟動的時候,就是通過讀取系統屬性dalvik.vm.heapsize的值來獲得Java Object Heap的最大值的,而ActivityManager類的成員函數getMemoryClass最終也通過讀取這個系統屬性的值來獲得Java Object Heap的最大值。
這個Java Object Heap的最大值也就是我們平時所說的Android應用程序進程能夠使用的最大內存。這里必須要注意的是,Android應用程序進程能夠使用的最大內存指的是能夠用來分配Java Object的堆。
Bitmap Memory也稱為External Memory,它是用來處理圖像的。在HoneyComb之前,Bitmap Memory是在Native Heap中分配的,但是這部分內存同樣計入Java Object Heap中,也就是說,Bitmap占用的內存和Java Object占用的內存加起來不能超過Java Object Heap的最大值。這就是為什么我們在調用BitmapFactory相關的接口來處理大圖像時,會拋出一個OutOfMemoryError異常的原因:
~~~
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
~~~
在HoneyComb以及更高的版本中,Bitmap Memory就直接是在Java Object Heap中分配了,這樣就可以直接接受GC的管理。
Native Heap就是在Native Code中使用malloc等分配出來的內存,這部分內存是不受Java Object Heap的大小限制的,也就是它可以自由使用,當然它是會受到系統的限制。但是有一點需要注意的是,不要因為Native Heap可以自由使用就濫用,因為濫用Native Heap會導致系統可用內存急劇減少,從而引發系統采取激進的措施來Kill掉某些進程,用來補充可用內存,這樣會影響系統體驗。
此外,在HoneyComb以及更高的版本中,我們可以在AndroidManifest.xml的application標簽中增加一個值等于“true”的android:largeHeap屬性來通知Dalvik虛擬機應用程序需要使用較大的Java Object Heap。事實上,在內存受限的手機上,即使我們將一個應用程序的android:largeHeap屬性設置為“true”,也是不能增加它可用的Java Object Heap的大小的,而即便是可以通過這個屬性來增大Java Object Heap的大小,一般情況也不應該使用該屬性。為了提高系統的整體體驗,我們需要做的是致力于降低應用程序的內存需求,而不是增加增加應用程序的Java Object Heap的大小,畢竟系統總共可用的內存是固定的,一個應用程序用得多了,就意味意其它應用程序用得少了。
二. 垃圾收集(GC)
Dalvik虛擬機可以自動回收那些不再使用了的Java Object,也就是那些不再被引用了的Java Object。垃圾自動收集機制將開發者從內存問題中解放出來,極大地提高了開發效率,以及提高了程序的可維護性。
我們知道,在C或者C++中,開發者需要手動地管理在堆中分配的內存,但是這往往導致很多問題。例如,內存分配之后忘記釋放,造成內存泄漏。又如,非法訪問那些已經釋放了的內存,引發程序崩潰。如果沒有一個好的C或者C++應用程序開發框架,一般的開發者根本無法駕馭內存問題,因為程序大了之后,很容易造成失控。最要命的是,內存被破壞的時候,并不一定就是程序崩潰的時候,它就是一顆不定時炸彈,說不準什么時候會被引爆,因此,查找原因是非常困難的。
從這里我們也可以推斷出,Android為什么會選擇Java而不是C/C++來作為應用程序開發語言,就是為了能夠讓開發遠離內存問題,而將精力集中在業務上,開發出更多更好的APP來,從而迎頭趕超iOS。當然,Android系統內存也存在大量的C/C++代碼,這只要考慮性能問題,畢竟C/C++程序的運行性能整體上還是優于運行在虛擬機之上的Java程序的。不過,為了避免出現內存問題,在Android系統內部的C++代碼,大量地使用了[智能指針](http://blog.csdn.net/luoshengyang/article/details/6786239)來自動管理對象的生命周期。選擇Java來作為Android應用程序的開發語言,可以說是技術與商業之間一個折衷,事實證明,這種折衷是成功的。
回到正題,在GingerBread之前,Dalvik虛擬使用的垃圾收集機制有以下特點:
1. Stop-the-world,也就是垃圾收集線程在執行的時候,其它的線程都停止;
2. Full heap collection,也就是一次收集完全部的垃圾;
3. 一次垃圾收集造成的程序中止時間通常都大于100ms。
在GingerBread以及更高的版本中,Dalvik虛擬使用的垃圾收集機制得到了改進,如下所示:
1. Cocurrent,也就是大多數情況下,垃圾收集線程與其它線程是并發執行的;
2. Partial collection,也就是一次可能只收集一部分垃圾;
3. 一次垃圾收集造成的程序中止時間通常都小于5ms。
Dalvik虛擬機執行完成一次垃圾收集之后,我們通常可以看到類似以下的日志輸出:
~~~
D/dalvikvm(9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms
~~~
在這一行日志中,GC_CONCURRENT表示GC原因,2049K表示總共回收的內存,3571K/9991K表示Java Object Heap統計,即在9991K的Java Object Heap中,有3571K是正在使用的,4703K/5261K表示External Memory統計,即在5261K的External Memory中,有4703K是正在使用的,2ms+2ms表示垃圾收集造成的程序中止時間。
三. 即時編譯(JIT)
前面提到,JIT是相對AOT而言的,即JIT是在程序運行的過程中進行編譯的,而AOT是在程序運行前進行編譯的。在程序運行的過程中進行編譯既有好處,也有壞處。好處在于可以利用程序的運行時信息來對編譯出來的代碼進行優化,而壞處在于占用程序的運行時間,也就是說不能花太多時間在代碼編譯和優化之上。
為了解決時間問題,JIT可能只會選擇那些熱點代碼進行編譯或者優化。根據2-8原則,一個程序80%的時間可能都是在重復執行20%的代碼。因此,JIT就可以選擇這20%經常執行的代碼來進行編譯和優化。
為了充分地利用好運行時信息來優化代碼,JIT采用一種激進的方法。JIT在編譯代碼的時候,會對程序的運行情況進行假設,并且按照這種假設來對代碼進行優化。隨著程序的代碼,如果前面的假設一直保持成立,那么JIT就什么也不用做,因此就可以提高程序的運行性能。一旦前面的假設不再成立了,那么JIT就需要對前面編譯優化的代碼進行調整,以便適應新的情況。這種調整成本可能是很昂貴的,但是只要假設不成立的情況很少或者幾乎不會發生,那么獲得的好處還是大于壞處的。由于JIT在編譯和優化代碼的時候,對程序的運行情況進行了假設,因此,它所采取的激進優化措施又稱為賭博,即Gambling。
我們以一個例子來說明這種Gambling。我們知道,Java的同步原語涉及到Lock和Unlock操作。Lock和Unlock操作是非常耗時的,而且它們只有在多線程環境中才真的需要。但是一些同步函數或者同步代碼,有程序運行的時候,有可能始終都是被單線程執行,也就是說,這些同步函數或者同步代碼不會被多線程同時執行。這時候JIT就可以采取一種Lazy Unlocking機制。
當一個線程T1進入到一個同步代碼C時,它還是按照正常的流程來獲取一個輕量級鎖L1,并且線程T1的ID會記錄在輕量鎖L1上。當經程T1離開同步函數或者同步代碼時,它并不會釋放前面獲得的輕量級鎖L1。當線程T1再次進入同步代碼C時,它就會發現輕量級鎖L的所有者正是自己,因此,它就可以直接執行同步代碼C。這時候如果另外一個線程T2也要進入同步代碼C,它就會發現輕量級鎖L已經被線程T1獲取。在這種情況下,JIT就需要檢查線程T1的調用堆棧,看看它是否還在執行同步代碼C。如果是的話,那么就需要將輕量級鎖L1轉換成一個重量級鎖L2,并且將重量級鎖L2的狀態設置為鎖定,然后再讓線程T2在重量級鎖L2上睡眠。等線程T1執行完成同步代碼C之后,它就會按照正常的流程來釋放重量級鎖L2,從而喚醒線程T2來執行同步代碼C。另一方面,如果線程T2在進入同步代碼C的時候,JIT通過檢查線程T1的調用堆棧,發現它已經離開同步代碼C了,那么它就直接將輕量級鎖L1的所有者記錄為線程T2,并且讓線程T2執行同步代碼C。
通過上述的Lazy Unlocking機制,我們就可以充分地利用程序的運行時信息來提高程序的執行性能,這種優化對于靜態編譯的語言來說,是無法做到的。從這個角度來看,我們就可以說,靜態編譯語言(如C++)并不一定比在虛擬機上執行的語言(如Java)快,這是因為后者可以有一種強大的武器叫做JIT。
Dalvik虛擬機從Android 2.2版本開始,才支持JIT,而且是可選的。在編譯Dalvik虛擬機的時候,可以通過WITH_JIT宏來將JIT也編譯進去,而在啟動Dalvik虛擬機的時候,可以通過-Xint:jit選項來開啟JIT功能。
關于虛擬機JIT的實現原理的簡要介紹,可以進一步參考這篇文章:[Hello, JIT World: The Joy of Simple JITs](http://blog.reverberate.org/2012/12/hello-jit-world-joy-of-simple-jits.html。)
四. Java本地調用(JNI)
無論如何,虛擬機最終都是運行在目標機器之上的,也就是說,它需要將自己的指令翻譯成目標機器指令來執行,并且有些功能,需要通過調用目標機器運行的操作系統接口來完成。這樣就需要有一個機制,使得函數調用可以從Java層穿越到Native層,也就是C/C++層。這種機制就稱為Java本地調用,即JNI。當然,我們在執行Native代碼的時候,有時候也是需要調用到Java函數的,這同樣是可以通過JNI機制來實現。也就是說,JNI機制既支持在Java函數中調用C/C++函數,也支持在C/C++函數中調用Java函數。
事實上,Dalvik虛擬機提供的Java運行時庫,大部分都是通過調用目標機器操作系統接口來實現的,也就是通過調用Linux系統接口來實現的。例如,當我們調用android.os.Process類的成員函數start來創建一個進程的時候,最終會調用到Linux系統提供的fork系統調用來創建一個進程。
同時,為了方便開發者使用C/C++語言來開發應用程序,Android官方提供了NDK。通過NDK,我們就可以使用JNI機制來在Java函數中調用到C/C++函數。不過Android官方是不提倡使用NDK來開發應用程序的,這從它對NDK的支持遠遠不如SDK的支持就可以看得出來。
五. 進程和線程管理
一般來說,虛擬機的進程和線程都是與目標機器本地操作系統的進程和線程一一對應的,這樣做的好處是可以使本地操作系統來調度進程和線程。進程和線程調度是操作系統的核心模塊,它的實現是非常復雜的,特別是考慮到多核的情況,因此,就完全沒有必要在虛擬機中提供一個進程和線程庫。
Dalvik虛擬機運行在Linux操作系統之上。我們知道,Linux操作系統并沒有純粹的線程概念,只要兩個進程共享同一個地址空間,那么就可以認為它們同一個進程的兩個線程。Linux操作系統提供了兩個fork和clone兩個調用,其中,前者就是用來創建進程的,而后者就是用來創建線程的。關于Linux操作系統的進程和線程的實現,可以參考在前面[Android學習啟動篇](http://blog.csdn.net/luoshengyang/article/details/6557518)一文中提到的經典Linux內核書籍。
關于Android應用程序進程,它有兩個很大的特點,下面我們就簡要介紹一下。
第一個特點是每一個Android應用程序進程都有一個Dalvik虛擬機實例。這樣做的好處是Android應用程序進程之間不會相互影響,也就是說,一個Android應用程序進程的意外中止,不會影響到其它的Android應用程序進程的正常運行。
第二個特點是每一個Android應用程序進程都是由一種稱為Zygote的進程fork出來的。Zygote進程是由init進程啟動起來的,也就是在系統啟動的時候啟動的。Zygote進程在啟動的時候,會創建一個虛擬機實例,并且在這個虛擬機實例將所有的Java核心庫都加載起來。每當Zygote進程需要創建一個Android應用程序進程的時候,它就通過復制自身來實現,也就是通過fork系統調用來實現。這些被fork出來的Android應用程序進程,一方面是復制了Zygote進程中的虛擬機實例,另一方面是與Zygote進程共享了同一套Java核心庫。這樣不僅Android應用程序進程的創建過程很快,而且由于所有的Android應用程序進程都共享同一套Java核心庫而節省了內存空間。
關于Dalvik虛擬機的特性,我們就簡要介紹到這里。事實上,Dalvik虛擬機和Java虛擬機的實現是類似的,例如,Dalvik虛擬機也支持JDWP(Java Debug Wire Protocol)協議,這樣我們就可以使用DDMS來調試運行在Dalvik虛擬機中的進程。對Dalvik虛擬機的其它特性或者實現原理有興趣的,建議都可以參考Java虛擬機的實現,這里提供三本參考書:
1. Java Virtual Machine Specification (Java SE 7)
2. Inside the Java Virtual Machine, Second Edition
3. Oracle JRockit: The Definitive Guide
另外,關于Dalvik虛擬機的指令集和dex文件格式的介紹,可以參考官方文檔:
[ART 和 Dalvik](https://source.android.com/devices/tech/dalvik/)
在這里,我們學習Dalvik虛擬機的目標是打通Java層到C/C++層之間的函數調用,從而可以更好地理解Android應用程序是如何在Linux內核上面運行的。為了達到這個目的,在接下來的文章中,我們將關注以下四個情景:
1. Dalvik虛擬機的啟動過程;
2. Dalvik虛擬機的運行過程;
3. JNI函數的注冊過程;
4. Java進程和線程的創建過程。
掌握了這四個情景之后,再結合前面的所有文章,我們就可以從上到下地打通整個Android系統了,敬請關注!
- 前言
- Android組件設計思想
- Android源代碼開發和調試環境搭建
- Android源代碼下載和編譯
- Android源代碼情景分析法
- Android源代碼調試分析法
- 手把手教你為手機編譯ROM
- 在Ubuntu上下載、編譯和安裝Android最新源代碼
- 在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
- 如何單獨編譯Android源代碼中的模塊
- 在Ubuntu上為Android系統編寫Linux內核驅動程序
- 在Ubuntu上為Android系統內置C可執行程序測試Linux內核驅動程序
- 在Ubuntu上為Android增加硬件抽象層(HAL)模塊訪問Linux內核驅動程序
- 在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
- 在Ubuntu上為Android系統的Application Frameworks層增加硬件訪問服務
- 在Ubuntu上為Android系統內置Java應用程序測試Application Frameworks層的硬件服務
- Android源代碼倉庫及其管理工具Repo分析
- Android編譯系統簡要介紹和學習計劃
- Android編譯系統環境初始化過程分析
- Android源代碼編譯命令m/mm/mmm/make分析
- Android系統鏡像文件的打包過程分析
- 從CM刷機過程和原理分析Android系統結構
- Android系統架構概述
- Android系統整體架構
- android專用驅動
- Android硬件抽象層HAL
- Android應用程序組件
- Android應用程序框架
- Android用戶界面架構
- Android虛擬機之Dalvik虛擬機
- Android硬件抽象層
- Android硬件抽象層(HAL)概要介紹和學習計劃
- Android專用驅動
- Android Logger驅動系統
- Android日志系統驅動程序Logger源代碼分析
- Android應用程序框架層和系統運行庫層日志系統源代碼分析
- Android日志系統Logcat源代碼簡要分析
- Android Binder驅動系統
- Android進程間通信(IPC)機制Binder簡要介紹和學習計劃
- 淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路
- 淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路
- Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析
- Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析
- Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析
- Android Ashmem驅動系統
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
- Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
- Android應用程序進程管理
- Android應用程序進程啟動過程的源代碼分析
- Android系統進程Zygote啟動過程的源代碼分析
- Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析
- Android應用程序消息機制
- Android應用程序消息處理機制(Looper、Handler)分析
- Android應用程序線程消息循環模型分析
- Android應用程序輸入事件分發和處理機制
- Android應用程序鍵盤(Keyboard)消息處理機制分析
- Android應用程序UI架構
- Android系統的開機畫面顯示過程分析
- Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
- SurfaceFlinger
- Android系統Surface機制的SurfaceFlinger服務
- SurfaceFlinger服務簡要介紹和學習計劃
- 啟動過程分析
- 對幀緩沖區(Frame Buffer)的管理分析
- 線程模型分析
- 渲染應用程序UI的過程分析
- Android應用程序與SurfaceFlinger服務的關系
- 概述和學習計劃
- 連接過程分析
- 共享UI元數據(SharedClient)的創建過程分析
- 創建Surface的過程分析
- 渲染Surface的過程分析
- Android應用程序窗口(Activity)
- 實現框架簡要介紹和學習計劃
- 運行上下文環境(Context)的創建過程分析
- 窗口對象(Window)的創建過程分析
- 視圖對象(View)的創建過程分析
- 與WindowManagerService服務的連接過程分析
- 繪圖表面(Surface)的創建過程分析
- 測量(Measure)、布局(Layout)和繪制(Draw)過程分析
- WindowManagerService
- WindowManagerService的簡要介紹和學習計劃
- 計算Activity窗口大小的過程分析
- 對窗口的組織方式分析
- 對輸入法窗口(Input Method Window)的管理分析
- 對壁紙窗口(Wallpaper Window)的管理分析
- 計算窗口Z軸位置的過程分析
- 顯示Activity組件的啟動窗口(Starting Window)的過程分析
- 切換Activity窗口(App Transition)的過程分析
- 顯示窗口動畫的原理分析
- Android控件TextView的實現原理分析
- Android視圖SurfaceView的實現原理分析
- Android應用程序UI硬件加速渲染
- 簡要介紹和學習計劃
- 環境初始化過程分析
- 預加載資源地圖集服務(Asset Atlas Service)分析
- Display List構建過程分析
- Display List渲染過程分析
- 動畫執行過程分析
- Android應用程序資源管理框架
- Android資源管理框架(Asset Manager)
- Asset Manager 簡要介紹和學習計劃
- 編譯和打包過程分析
- Asset Manager的創建過程分析
- 查找過程分析
- Dalvik虛擬機和ART虛擬機
- Dalvik虛擬機
- Dalvik虛擬機簡要介紹和學習計劃
- Dalvik虛擬機的啟動過程分析
- Dalvik虛擬機的運行過程分析
- Dalvik虛擬機JNI方法的注冊過程分析
- Dalvik虛擬機進程和線程的創建過程分析
- Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃
- Dalvik虛擬機Java堆創建過程分析
- Dalvik虛擬機為新創建對象分配內存的過程分析
- Dalvik虛擬機垃圾收集(GC)過程分析
- ART虛擬機
- Android ART運行時無縫替換Dalvik虛擬機的過程分析
- Android運行時ART簡要介紹和學習計劃
- Android運行時ART加載OAT文件的過程分析
- Android運行時ART加載類和方法的過程分析
- Android運行時ART執行類方法的過程分析
- ART運行時垃圾收集機制簡要介紹和學習計劃
- ART運行時Java堆創建過程分析
- ART運行時為新創建對象分配內存的過程分析
- ART運行時垃圾收集(GC)過程分析
- ART運行時Compacting GC簡要介紹和學習計劃
- ART運行時Compacting GC堆創建過程分析
- ART運行時Compacting GC為新創建對象分配內存的過程分析
- ART運行時Semi-Space(SS)和Generational Semi-Space(GSS)GC執行過程分析
- ART運行時Mark-Compact( MC)GC執行過程分析
- ART運行時Foreground GC和Background GC切換過程分析
- Android安全機制
- SEAndroid安全機制簡要介紹和學習計劃
- SEAndroid安全機制框架分析
- SEAndroid安全機制中的文件安全上下文關聯分析
- SEAndroid安全機制中的進程安全上下文關聯分析
- SEAndroid安全機制對Android屬性訪問的保護分析
- SEAndroid安全機制對Binder IPC的保護分析
- 從NDK在非Root手機上的調試原理探討Android的安全機制
- APK防反編譯
- Android視頻硬解穩定性問題探討和處理
- Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
- Android應用程序安裝過程源代碼分析
- Android應用程序啟動過程源代碼分析
- 四大組件源代碼分析
- Activity
- Android應用程序的Activity啟動過程簡要介紹和學習計劃
- Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
- 解開Android應用程序組件Activity的"singleTask"之謎
- Android應用程序在新的進程中啟動新的Activity的方法和過程分析
- Service
- Android應用程序綁定服務(bindService)的過程源代碼分析
- ContentProvider
- Android應用程序組件Content Provider簡要介紹和學習計劃
- Android應用程序組件Content Provider應用實例
- Android應用程序組件Content Provider的啟動過程源代碼分析
- Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
- Android應用程序組件Content Provider的共享數據更新通知機制分析
- BroadcastReceiver
- Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
- Android應用程序注冊廣播接收器(registerReceiver)的過程分析
- Android應用程序發送廣播(sendBroadcast)的過程分析