d8
是 Android Studio 和 Android Gradle 外掛程式的指令列工具,可將專案的 Java 位元碼編譯為在 Android 裝置上執行的 DEX 位元碼,而且可讓您在應用程式的程式碼中使用 Java 8 語言功能。
d8
也包含在 Android Build Tools 28.0.1 以上版本的獨立工具中:android_sdk/build-tools/version/
。
一般使用情況
d8
使用相當簡單,您只需要將要編譯的 Java 位元碼路徑轉換為 DEX 位元碼 (如下所示),
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 位元碼。不過,d8 會包含一些資訊,用來產生堆疊追蹤和記錄例外狀況。編譯公開發布的位元碼時,請傳遞這個旗標。 |
--output path
|
指定 DEX 輸出的所需路徑。根據預設,d8 會輸出目前工作目錄中的 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 位元碼。這個旗標對執行漸進式建構作業時相當實用,而不是編譯在裝置上執行的最佳化 DEX 檔案,d8 會建立中繼 DEX 檔案,並儲存在指定的輸出或預設路徑中。如要編譯您想在裝置上執行的 DEX 檔案,請排除這項旗標,並指定中繼 DEX 類別的路徑做為輸入。 |
--file-per-class
|
將每個類別編譯成不同的 DEX 檔案。 啟用此旗標後,您可以重新編譯已變更類別,以執行更多漸進式建構作業。使用 Android Gradle 外掛程式執行漸進式建構作業時,系統會預設啟用這項最佳化功能。 指定 |
--no-desugaring
|
停用 Java 8 語言功能。除非您不打算編譯使用 Java 8 語言功能的 Java 位元碼,才需要使用這個標記。 |
--main-dex-list path
|
指定列出 d8 類別的文字檔案,其中應包含在主要 DEX 檔案中,且名稱通常為 classes.dex 。換言之,如果您使用這個旗標未指定類別清單,d8 就無法保證主要 DEX 檔案包含哪些類別。由於 Android 系統會在您啟動應用程式時優先載入主要 DEX 檔案,因此您可以在啟動應用程式時使用這個旗標,將特定類別編譯成主要 DEX 檔案,優先排定這些類別。在支援舊版 Multidex 檔案時,這項功能尤其實用,因為在載入舊版 Multidex 程式庫前,僅有主要 DEX 檔案中的類別可以使用。 請注意,每個 DEX 檔案都必須符合 64K 參考資料上限。因此,請勿為主要 DEX 檔案指定太多類別,否則會收到編譯錯誤。根據預設,使用 指定 |
--version
|
列印目前使用的 d8 版本。 |
--help
|
列印使用 d8 的說明文字 |
執行漸進式建構作業
如要改善開發期間的建構速度 (例如進行持續整合建構作業),請指示 d8
只編譯專案 Java 位元碼的的部分。例如,如果您啟用每個類別的 dex,即可僅重新編譯自上次建構之後已修改的類別。
下列指令會執行幾個類別的漸進式建構,並啟用每個類別的內容排除功能。這個指令也會指定漸進式建構作業的輸出目錄。
d8 MainActivity.class R.class --intermediate --file-per-class --output ~/build/intermediate/dex
當 d8
執行漸進式建構作業時,會在 DEX 輸出中儲存其他資訊,之後用於在應用程式的完整構建期間正確處理 --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
可讓您透過名為 Deugaring 的編譯程式,在您的程式碼中使用 Java 8 語言功能,這些實用的語言功能會轉換為位元碼,可在 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