d8
是 Android Studio 和 Android Gradle 外掛程式的指令列工具,可將專案的 Java 位元碼編譯為在 Android 裝置上執行的 DEX 位元碼。d8
可讓您在應用程式的程式碼中使用 Java 8 的語言功能。
d8
也包含在 Android Build Tools 28.0.1 以上版本的獨立工具中:android_sdk/build-tools/version/
。
一般使用情況
d8
只需要一個連往您想要轉換為 DEX 位元碼的已編譯 Java 位元碼路徑。例如:
d8 MyProject/app/build/intermediates/classes/debug/*/*.class
輸入的位元碼可以是 *.class
檔案或容器的任意組合,例如 JAR、APK 或 ZIP 檔案。您也可以加入 d8
的 DEX 檔案,將這些檔案合併到 DEX 輸出中,這在納入漸進式版本的輸出內容時相當實用。
根據預設,d8
會將 Java 位元碼編譯成最佳化的 DEX 檔案,並含有可在執行階段期間對程式碼進行偵錯的偵錯資訊。不過,您可以加入選用的旗標來執行漸進式版本、指定應編譯為主要 DEX 檔案的類別,以及指定使用 Java 8 語言功能所需的其他資源路徑。
d8 path-to-input-files [options]
下表說明了您可以與 d8
搭配使用的選用旗標。
選項 | 說明 |
---|---|
--debug
|
編譯 DEX 位元碼以納入偵錯資訊,例如偵錯符號表。 這個選項預設為啟用。如要在 DEX 位元碼中包含偵錯資訊, 為應用程式或程式庫的發布版本編譯 DEX 檔案時,請改用 |
--release
|
編譯不含偵錯資訊的 DEX 位元碼。不過, 在針對公開版本編譯位元碼時傳送這個旗標。 |
--output path
|
指定 DEX 的輸出路徑。根據預設,
如果您指定 ZIP 或 JAR 檔案的路徑和名稱, |
--lib android_sdk/platforms/api-level/android.jar
|
指定 Android SDK 的 android.jar 路徑。編譯使用 Java 8 語言功能的位元碼時必須使用這個旗標。 |
--classpath path
|
指定 d8 所需的類別路徑資源,以編譯專案的 DEX 檔案。特別是 d8 必須在編譯使用 Java 8 語言功能的位元碼時指定某些資源。 |
--min-api number
|
指定輸出 DEX 檔案支援的最低 API 級別。 |
--intermediate
|
傳遞這個旗標,讓 d8 知道您並非編譯完整的專案 Java 位元碼。在執行漸進式版本時這個標記很實用。d8 不會編譯出預期在裝置上執行的最佳化 DEX 檔案,而是建立一個中繼 DEX 檔案,並儲存在指定的輸出或預設路徑中。如要編譯您想在裝置上執行的 DEX 檔案,請排除這項旗標,並指定中繼 DEX 類別的路徑做為輸入。 |
--file-per-class
|
將每個類別編譯成不同的 DEX 檔案。 啟用此旗標後,您可以只針對已變更的類別重新編譯,以執行更多漸進式的版本。使用 Android Gradle 外掛程式執行漸進式版本時,系統預設會啟用這項最佳化功能。 指定 |
--no-desugaring
|
停用 Java 8 語言功能。若您不打算編譯使用 Java 8 語言功能的 Java 位元碼,才需要使用到這個旗標。 |
--main-dex-list path
|
指定一個文字檔,其中列出了 由於 Android 系統會在您啟動應用程式時優先載入主要的 DEX 檔案,因此您可以在啟動應用程式時使用這個旗標,將特定類別編譯成主要 DEX 檔案,優先排定這些類別。在支援舊版 Multidex 檔案時,這項功能尤其實用,因為在載入舊版 Multidex 程式庫前,只有主要的 DEX 檔案中的類別可以使用。 請注意,每個 DEX 檔案仍必須符合 64K 參考資料上限的規定。因此,請勿為主要 DEX 檔案指定過多類別,否則會發生編譯錯誤。根據預設,使用 指定 |
--pg-map file
|
使用 file 做為發布的對應檔案。 |
--file-per-class-file
|
為每個輸入 .class 檔案產生獨立的 DEX 檔案。 在合成類別中保有原始類別。 |
--desugared-lib file
|
指定脫糖程序的程式庫設定。 file 是 JSON 格式的脫糖程式庫設定檔。 |
--main-dex-rules file
|
Proguard 保有將類別存放在主要 DEX 檔案中的規則。 |
--pg-map file
|
使用 file 做為發布的對應檔案。 |
--main-dex-list-output file
|
在 |
|
強制啟用 javac 產生的斷言程式碼。
|
|
強制停用 javac 產生的斷言程式碼。這是產生 DEX 檔案時對 javac 斷言程式碼的預設處理作業。 |
|
請勿變更 javac 產生的斷言程式碼。這是在產生 class 檔案時,對 javac 斷言程式碼的預設處理作業。 |
|
變更 javac 和 kotlinc 產生的斷言程式碼,透過每個斷言錯誤叫用 handler method 方法,而不是擲回該錯誤。handler method 會指定為類別名稱,後面接著一個點和方法的名稱。這個處理常式方法必須使用一個 java.lang.Throwable 類型的引數,並且傳回類型 void 。 |
--thread-count number of threads
|
指定要用於編譯的執行緒數量。如未指定,該數量會以經驗法則為準,同時將核心數量納入考量。 |
--map-diagnostics[
:type] from-level to-level
|
將 type 的診斷 (預設為所有) 以 from-level 回報給 to-level,其中 from-level 和 to-level 是「資訊」、「警告」、或「錯誤」之一,而選擇性的 type 則為診斷的簡單或完整 Java 類型名稱。如果未指定 type,系統會對應 from-level 中的所有診斷資料。請注意,無法對應編譯器的嚴重錯誤。 |
--version
|
列印目前使用的 d8 版本。 |
--help
|
列印使用 d8 的說明文字。 |
執行漸進式建構
如要改善開發期間的建構速度 (例如進行持續整合建構作業),指示 d8
只編譯專案中 Java 位元碼的部分。例如,如果您啟用每個類別的 dex,即可僅重新編譯上一個版本後所修改的類別即可。
下列指令會執行幾個類別的漸進式建構,並啟用每個類別的內容排除功能。這個指令也會指定漸進式建構作業的輸出目錄。
d8 MainActivity.class R.class --intermediate --file-per-class --output ~/build/intermediate/dex
當 d8
執行漸進式建構作業時,會在 DEX 輸出中儲存其他資訊。d8
稍後會使用該資訊來正確處理 --main-dex-list
選項,並在應用程式的完整建構期間將 DEX 檔案合併。
舉例來說,處理 Java 8 lambda 類別時,d8
會追蹤每個輸入類別所建立的 lambda 類別。在完整建構作業中,當 d8
在主要 DEX 檔案中納入類別時,系統會查詢中繼資料,以確保為該類別建立的所有 lambda 類別也納入至主 DEX 檔案中。
如果您已將專案的所有位元碼編譯成多個漸進式建構作業的 DEX 檔案,請將中繼 DEX 檔案的目錄傳遞至 d8
以執行完整的建構作業,如下列指令所示。此外,您還可以使用 --main-dex-list
指定要讓 d8
編譯到主要 DEX 檔案中的類別。由於輸入內容是已編譯為 DEX 位元碼的一組檔案,因此這項建構作業的執行速度應會比乾淨的建構作業更快。
d8 ~/build/intermediate/dex --release --main-dex-list ~/build/classes.txt --output ~/build/release/dex
編譯使用 Java 8 語言功能的位元碼
d8
可讓您透過名為 Desugaring 的編譯程式,在您的程式碼中使用 Java 8 語言功能。Desugaring 可將這些實用的語言功能轉換為位元碼,可在 Android 平台上執行。
Android Studio 和 Android Gradle 外掛程式包含 d8
為您啟用 Desugaring 所需的類別路徑資源。不過,透過指令列使用 d8
時,您必須自行加上。
這類資源之一為目標 Android SDK 的 android.jar
。這項資源包含一組 Android 平台的 API。請使用 --lib
旗標指定路徑。
另一項資源是編譯至專案中的 Java 位元碼組合,這些位元碼目前並未編譯至 DEX 位元碼,但需要將其他類別編譯成 DEX 位元碼。
例如,如果您的程式碼使用預設和靜態介面方法 (為 Java 8 語言的功能),您必須使用此旗標來指定所有專案的 Java 位元碼路徑 (即使您並不打算將所有程式碼編譯成 DEX 位元碼)。這是因為 d8
需要這些資訊瞭解專案的程式碼,並解析對介面方法的呼叫。
下列程式碼範例會針對可存取預設介面方法的類別,執行漸進式建構作業:
d8 MainActivity.class --intermediate --file-per-class --output ~/build/intermediate/dex --lib android_sdk/platforms/api-level/android.jar --classpath ~/build/javac/debug