1. 程式人生 > >Android首次啟動時間長優化之預編譯提取Odex

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為字尾名,格式如:
[email protected]
@[email protected]@classes.dex)。     如果當前運行於Art模式下,    Art同樣會在首次進入系統的時候呼叫/system/bin/dexopt工具來將dex位元組碼翻譯成本地機器碼,儲存在data/dalvik-cache下。     那麼這裡需要注意的是,無論是對dex位元組碼進行優化,還是將dex位元組碼翻譯成本地機器碼,最終得到的結果都是儲存在相同名稱的一個odex檔案裡面的,但是前者對應的是一個dey檔案(表示這是一個優化過的dex),後者對應的是一個oat檔案(實際上是一個自定義的elf檔案,裡面包含的都是本地機器指令)。簡單來說無論是Art模式,還是DVM,優化的結果都是一個odex檔案,只是這兩種odex檔案有著本質的區別(一個是dey位元組碼,一個是oat機器碼)。之所以這麼設計,主要通過這種方式,原來任何通過絕對路徑引用了該odex檔案的程式碼就都不需要修改了,可以理解為這是art與dalvik相容的結果。     由於在系統首次啟動時會對應用進行安裝,那麼在預置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應用提取的方法如下:
    在目錄\build\core\dex_preopt_odex_install.mk中新增紅色標記的程式碼:
ifeq ($(LOCAL_MODULE),helloworld)
LOCAL_DEX_PREOPT:=
endif
build_odex:=
installed_odex:=
....
helloworld可替換為需要跳過提取odex的apk的LOCAL_MODULE名字,如Settings等。

相關推薦

Android首次啟動時間優化編譯提取Odex

    提示!應用程式的安裝有兩種情況,第一:首次啟動系統時安裝;第二:系統啟動完成後安裝。本篇博文基於第一種安裝場景。在系統首次啟動的場景中,系統會對/system/app、/system/priv-app、/data/app目錄下的所有APK進行dex位元組碼到本地機器

解決Android首次啟動APP時,顯示空白頁或者黑屏時間的問題

問題描述: 第一次啟動app(冷啟動,如果不明白冷啟動和熱啟動的話,可以百度一下),會出現白屏或者黑屏,而且當代碼量增多的時候,出現的時間很長。這樣的使用者體驗多不好。下面我寫了一個小例子,先模擬一下該問題的效果圖,以及解決問題後的效果圖。處理前有空白頁如圖1,

Hbase優化分割槽

    如果在hbase shell中使用create建表時只寫了表名和列族名,那麼這張表將只有一個region ,當一個region的大小超過閾值時會自動split成兩個,但split操作會帶來資源消耗。region個數太少時,在資料量大、訪問量大,或被批處

Hbase優化分割槽設計

1. 背景 HBase建表時預設只有一個region,這個region的rowkey是沒有邊界的,即沒有startkey和endkey。在資料寫入時,所有資料都會寫入這個預設的region。隨著資料量的不斷增加,這個預設的region會越來越大,當達到某個閾值會自動split成為2個

Android APP啟動時間測試

使用命令: adb.exe shell am start -W com.doctorapp/com.doctorapp.MainActivity WaitTime 返回從 startActivity 到應用第一幀完全顯示這段時間. 就是總的耗時,包括前一

Android app啟動白屏優化

可以看到啟動的時候會有一個白屏, 如果手機較慢的話, 這個白屏就會持續一段時間, 不太友好. 那麼還有沒有什麼辦法優化呢? 給我們的應用視窗弄一個PlaceHolder Android最新的Material Design有這麼個建議的. 建議我們使用一

android 統計啟動,標準

一.啟動的型別 冷啟 動,application沒有被建立,需要先建立程序,然後啟動MainActivity。由於這個過程需要fork一個新程序,所以耗時。 熱啟動,同上面對照,已經啟動過application,並駐留在系統記憶體內,只是需要喚醒該程序,並啟動MainActivity。 二:統計啟動時間

Android 系統啟動時間分析

執行命令 adb logcat -d -b events | grep boot I/boot_progress_start(   71): 2000 I/boot_progress_preload

Android系統啟動時間(不是系統當前時間)的獲取

1》.查裡很多資料,並沒有找到直接獲取系統啟動時間(不是系統當前時間)的ApI; 思路轉換為:接收系統的開機廣播,在廣播裡面獲取當前的時間; 2》.注意幾點: 1.BootUPReceiver廣播類

Android相機開發(一)覽拍照檢視圖片基本功能的實現

前言         接觸Android開發有一段時間了。一開始時純粹是出於自己的興趣,空閒時寫幾個小軟體自娛自樂。剛好暑假時老闆佈置的任務跟Android相關,所以這段時間又繼續進行了Android的開發學習。現在的Android開發水平僅屬於

Android佈局優化使用style提取重複使用屬性

如何優化佈局程式碼?使之看起來既簡潔又得到優化呢? 在專案中寫佈局的時候常常會遇到很多空間使用到了很多相同的屬性,例如一個TextView使用到了marginLeft和marginRight,其他很

js編譯

預編譯過程 1.建立AO物件 2.找形參和變數宣告,將變數和形參名作為AO屬性名,值為undefined 3.將實參值和形參統一 4.在函式體裡面找函式宣告,值賦予函式體 程式碼: <!DOCTYPE html> <html lang="en"> <head&g

JDBC程式設計編譯SQL與防注入式攻擊以及PreparedStatement

  在JDBC程式設計中,常用Statement、PreparedStatement 和 CallableStatement三種方式來執行查詢語句,其中 Statement 用於通用查詢, PreparedStatement 用於執行引數化查詢,而 CallableState

Try increasing heap size with java option '-XmxAndroid 7.0工程編譯jack伺服器

stackoverflow Try increasing heap size with java option ‘-Xmx export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation

Visual Studio 2008 常見錯誤解決 編譯

今天照著MSDN中的例子寫了一個程式,莫名其妙的出現了這樣的錯誤(難道官方的程式碼也不可靠!?): warning C4627: “#include <iostream>”: 在查詢預編譯頭使用時跳過 warning C4627: “#include "Math

JavaScript 編譯 作用域,作用域鏈

每次 生成 代碼 引用 空間 小白 ati pro function 第一次寫博客,本來是學習jQuery遇到閉包問題,發現並沒有理解閉包,發現閉包牽扯的知識點太多。復習了一遍(發現自己該記住的全忘了)寫在博客裏,自己也是小白,希望大神們指點迷津,必將感激不盡。 我們知道J

android專案效能優化啟動時間

一般來說,判定一個android專案效能優劣,我們有以下幾個指標: 啟動時間 apk大小 UI渲染 穩定性 記憶體佔用 電量消耗 接下來,讓我們就這幾個指標展開來詳述各自究竟應該怎樣去優化。 啟動時間 一般來說,應用啟動時間分為三種 首次啟動

Android效能優化 App啟動原理分析及速度和時間優化

應用的啟動速度緩慢這是很多開發者都遇到的一個問題,比如啟動緩慢導致的黑屏,白屏問題,大部分的答案都是做一個透明的主題,或者是做一個Splash介面,但是這並沒有從根本上解決這個問題。那麼如何從根本上解決這個問題或者做到一定程度的緩解? 一、應用的啟動方式 1、冷啟動:

解決首次啟動程式白屏時間的問題(針對Android Studio Instant Run)

轉自郭霖大神: Android Studio中新加入的Instant Run功能,使得我們開發的效率可以大大地提升(詳情見上一篇部落格)。 問題重現 我初次發現這個問題是在升級了Android Studio 2.0之後,當時Android Studio的版本是從1.5直

安卓性能優化計算apk啟動時間

height let 邏輯 第一個 cin 16px box tex 性能 之前有人在知乎提問:“怎麽計算apk的啟動時間?” : 利用Python或者直接用adb命令怎麽計算apk的啟動時間呢?就是計算從點擊圖標到apk完全啟動所花費的時間。比如,對遊戲來說就是點擊遊