art虛擬機介紹


  Android 4.4提供了一種與Dalvik截然不同的運行環境ART(Android runtime)支持,ART源於google收購的Flexycore的公司。ART模式與Dalvik模式最大的不同在於,啟用ART模式后,系統在安裝應用的時候會進行一次預編譯,將字節碼轉換為機器語言存儲在本地,這樣在運行程序時就不會每次都進行一次編譯了,執行效率也大大提升。這種編譯的方式與c++,c語言編譯方式蠻像。

  虛擬機切換設置

  Settings> Developer Options> Select Runtime

ART優點     
   1、系統性能的顯著提升。     
   2、應用啟動更快、運行更快、體驗更流暢、觸感反饋更及時。     
   3、更長的電池續航能力。
   4、支持更低的硬件。


ART缺點    
  1、更大的存儲空間占用,可能會增加10%-20%。
  2、更長的應用安裝時間。

Dalvik虛擬機性能優化
     1、DEX代碼安裝時或第一次動態加載時odex化處理。
     2、Android2.3版本提供了JIT機制提升性能;

      JIT(Just-In-Time),用來在運行時動態地將執行頻率很高的dex字節碼編譯成本地機器碼,然后再執行。通過JIT,就可以有效地提高Dalvik虛擬機的執行效率。但是,應用每次運行的時候,部分字節碼都需要通過JIT轉換為機器碼,降低了應用程序運行效率。而ART則是使用AOT進行處理(Ahead-Of-Time),所謂AOT是指在運行以前就把中間代碼靜態編譯成本地代碼,這就減去了JIT運行時的轉換時間,因此,即使Dalvik采用了JIT,Dalvik總體性能還是不能與直接執行本地機器碼的ART虛擬機相比。

AOT的編譯器分兩種模式:
  1. 在開發機上編譯預裝應用;
          C/C++開發應用程序的時候,編譯器直接就把它們翻譯成目標機器碼。
  2. 在設備上編譯新安裝的應用;
          在應用安裝時將dex字節碼翻譯成本地機器碼。

 art執行功能類圖如下:

 

  通過上圖我們可以總結出這樣的結論:

  ①在JNI_CreateJavaVM()中,先是調用Create()函數來創建Runtime。Runtime是個單例,創建出來后緊接着調用Init()函數(/art/runtime/runtime.cc)。Init()函數會做很多初始化工作:解析參數,初始化Heap和JavaVMExt結構,線程和信號處理,創建ClassLinker等。

  ②接着調用ClassLinker的FindClass()查找目標類,其中涉及幾個關鍵函數:LookupClass(),DefineClass(),InsertClass(),LoadClass()和LinkClass()。以下簡要介紹下它們的主要功能:

  LookupClass()先在ClassLinker的成員變量class_table_中找指定類,找到就返回,找不到的話看是否要在image中找(class_loader為NULL且dex_cache_image_class_lookup_required為true)。如果要的話就調用LookupClassFromImage()在Image中進行查找,找到了就調用InsertClass()將找到的類放入到class_table_中方便下次查找。

  DefineClass()做了很多事情,包括了LoadClass(),InsertClass()和LinkClass()等動作。其中,LoadClass()調用LoadField()和LoadMethod()等函數把類中的域和方法數據從dex文件中讀出來,填入Class結構。
  InsertClass()主要功能是把該類寫入class_table_中方便下次查找。
  LinkClass()顧名思義,就是動態綁定虛函數和接口函數了。其調用結構:
  LinkSuperClass() // 檢查父類。
  LinkMethods()
  LinkVirtualMethods() // 結合父類進行虛函數綁定,填寫Class中的虛函數表vtable_。
  LinkInterfaceMethods() //處理接口類函數信息iftable_。注意接口類中的虛函數也會影響虛函數表,因此會更新vtable_。
  LinkInstanceFields() & LinkStaticFields() // 更新域信息,如域中的Offset和類的對象大小等。

  對於FindClass()來說,類大體有以下幾種情況:內置類,啟動類,系統類和其它。內置類是很基本的類,一般是初始化時預加載好的(如WellKnownClasses和JniConstants里那一坨),它們可以通過LookupClassFromImage()函數找到。啟動類是在BOOTCLASSPATH里的類,由於它們是啟動類,所以這里還沒有ClassLoader。除掉前面的內置類,其余的通過DexFile::FindInClassPath()查找得到。再就是系統類和其它類,它們的加載過程是類似的,都是通過ClassLoader的loadClass方法,區別在於前者通過特殊的SystemClassLoader進行加載。舉例來說,對於一個還沒被加載過的啟動類,一般流程是這樣的:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM