Android初次開機時間長最佳化之先行編譯提取Odex

來源:互聯網
上載者:User

Android初次開機時間長最佳化之先行編譯提取Odex
提示!應用程式的安裝有兩種情況,第一:初次開機系統時安裝;第二:系統啟動完成後安裝。本篇博文基於第一種安裝情境。在系統初次開機的情境中,系統會對/system/app、/system/priv-app、/data/app目錄下的所有APK進行dex位元組碼到本地機器碼的翻譯,同樣也會對/system/framework目錄下的APK或者JAR檔案,以及這些APK所引用的外部JAR,進行dex位元組碼到本地機器碼的翻譯。這樣可以保證除了應用之外,系統中使用Java來開發的系統服務,也會統一地從dex位元組碼翻譯成本地機器碼。詳細內容請移步老羅的部落格Android ART運行時無縫替換Dalvik虛擬機器的過程分析。
一、JVM、DVM、ART虛擬機器瞭解

JVM虛擬機器啟動並執行是java位元組碼: java->java bytecode(class)->java bytecode(jar) 注!java虛擬機器基於棧,基於棧的機器必須使用指令來載入和操作棧上的資料,所需指令相對來說比較多。
Dalvik虛擬機器解釋執行的dex位元組碼: java->java bytecode(class)->dalvik bytecode(dex) 註:相對JVM,Dalvik基於寄存器,且經過最佳化並允許有限的記憶體中同時運行多個虛擬機器執行個體,每個Dalvik應用作為一個獨立的Linxu進程執行。如果一個應用中有很多類,編譯後會相應產生很多class檔案,class檔案之間也會有不少冗餘資訊,dex格式檔案把所有classs檔案內容整合到一個檔案,這樣可以減少整體檔案佔用,IO操作,同時也提高了類的尋找速度。此外,dex格式檔案增加了新的作業碼支援,檔案結構也相對簡潔,使用等長的指令來提高解析速度。而且dex檔案會盡量擴大隻讀結構的大小,來提高進程間資料共用的速度。
ART虛擬機器執行的本地機器碼: java->java bytecode(class)->dalvik bytecode(dex)->optimized android runtime machine code(oat) 註:ART所使用的AOT(Ahead-Of-Time)編譯,在應用首次安裝時,位元組碼先行編譯成機器碼儲存在本地,也就是說在程式運行前編譯。而Dalvik是典型的JIT(Just_In_Time),此模式下,應用 每次啟動並執行時候,位元組碼都需要即時編譯器轉換為機器碼再執行,也就是在程式運行時編譯。因此在App運行時,ART模式相對於Dalvik省去瞭解釋位元組碼的過程,佔用記憶體也相應減少,進而提高App的運行效率。
二、Odex
從上面一節中我們知道,在編譯打包APK時,Java類會被編譯成一個或者多個位元組碼檔案(.class),通過dx工具CLASS檔案轉換成一個DEX(Dalvik Executable)檔案。 通常情況下,我們看到的Android應用程式實際上是一個以.apk為尾碼名的壓縮檔。我們可以通過壓縮公用程式對apk進行解壓,解壓出來的內容中有一個名為classes.dex的檔案。那麼我們首次開機的時候系統需要將其從apk中解壓出來儲存在data/app目錄中。 如果當前運行在Dalvik虛擬機器下,Dalvik會對classes.dex進行一次“翻譯”,“翻譯”的過程也就是守護進程installd的函數dexopt來對dex位元組碼進行最佳化,實際上也就是由dex檔案產生odex檔案,最終odex檔案被儲存在手機的VM緩衝目錄data/dalvik-cache下(注意!這裡所產生的odex檔案依舊是以dex為尾碼名,格式如:system@priv-app@Settings@Settings.apk@classes.dex)。 如果當前運行於Art模式下, Art同樣會在首次進入系統的時候調用/system/bin/dexopt工具來將dex位元組碼翻譯成本地機器碼,儲存在data/dalvik-cache下。 那麼這裡需要注意的是,無論是對dex位元組碼進行最佳化,還是將dex位元組碼翻譯成本地機器碼,最終得到的結果都是儲存在相同名稱的一個odex檔案裡面的,但是前者對應的是一個dey檔案(表示這是一個最佳化過的dex),後者對應的是一個oat檔案(實際上是一個自訂的elf檔案,裡麵包含的都是本地機器指令)。通過這種方式,原來任何通過絕對路徑引用了該odex檔案的代碼就都不需要修改了。 由於在系統初次開機時會對應用進行安裝,那麼在預置APK比較多的情況下,將會大大增加系統初次開機的時間。從前面的描述可知,既然無論是DVM還是ART,對DEX的最佳化結果都是儲存在一個相同名稱的odex檔案,那麼如果我們把這兩個過程在ROM編譯的時候預先處理提取Odex檔案將會大大最佳化系統初次開機的時間。

三、先行編譯提取Odex
在BoardConfig.mk中定義:WITH_DEXPREOPT := true。開啟這個宏之後,無論是有源碼還是無源碼的預置apk先行編譯時都會提取odex檔案。
不過這裡需要注意的是開啟WITH_DEXPREOPT 宏之後,先行編譯時提取Odex會增加一定的空間,預置太多apk,會導致system.img 過大,而編譯不過。遇到這種情況可以通過刪除apk中的dex檔案、調大system.img的大小限制,或在先行編譯時跳過一些apk的odex提取。 例如跳過helloworld應用提取的方法如下:
在目錄uildcoredex_preopt_odex_install.mk中添加紅色標記的代碼:
i feq ($(LOCAL_MODULE),helloworld)
LOCAL_DEX_PREOPT:=
endif
build_odex:=
installed_odex:=
....
helloworld可替換為需要跳過提取odex的apk的LOCAL_MODULE名字,如Settings等。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.