d8

d8 ist ein Befehlszeilentool, mit dem Android Studio und das Android-Gradle-Plug-in den Java-Bytecode Ihres Projekts in DEX-Bytecode kompilieren können, der auf Android-Geräten ausgeführt wird. Mit d8 können Sie die Sprachfunktionen von Java 8 im Anwendungscode verwenden.

d8 ist auch als eigenständiges Tool in Android Build Tools 28.0.1 und höher enthalten: android_sdk/build-tools/version/.

Allgemeine Verwendung

d8 erfordert nur einen Pfad zum kompilierten Java-Bytecode, den Sie in DEX-Bytecode umwandeln möchten. Beispiele:

d8 MyProject/app/build/intermediates/classes/debug/*/*.class

Der Eingabe-Bytecode kann in einer beliebigen Kombination aus *.class-Dateien oder Containern sein, z. B. JAR-, APK- oder ZIP-Dateien. Sie können auch DEX-Dateien einschließen, damit d8 in die DEX-Ausgabe zusammengeführt wird. Dies ist nützlich, wenn Sie die Ausgabe aus einem inkrementellen Build einbeziehen.

Standardmäßig kompiliert d8 den Java-Bytecode in optimierte DEX-Dateien und enthält Informationen zur Fehlerbehebung, mit denen Sie während der Laufzeit Fehler im Code beheben können. Sie können jedoch optionale Flags einfügen, um einen inkrementellen Build auszuführen, Klassen angeben, die in der DEX-Hauptdatei kompiliert werden sollen, und Pfade zu zusätzlichen Ressourcen angeben, die zur Verwendung der Java 8-Sprachfunktionen erforderlich sind.

d8 path-to-input-files [options]

In der folgenden Tabelle werden die optionalen Flags beschrieben, die Sie mit d8 verwenden können:

Option Beschreibung
--debug

Kompilieren Sie den DEX-Bytecode mit Informationen zur Fehlerbehebung, z. B. mit Symboltabellen für die Fehlerbehebung.

Diese Option ist standardmäßig aktiviert. Damit dem DEX-Bytecode Informationen zur Fehlerbehebung hinzugefügt werden können, erwartet d8, dass der Java-Eingabecode diese Informationen enthält. Wenn Sie beispielsweise javac zum Kompilieren Ihres Codes verwenden, müssen Sie das Flag -g übergeben, um Fehlerbehebungsinformationen in den Java-Ausgabebytecode aufzunehmen.

Verwenden Sie beim Kompilieren von DEX-Dateien für die Release-Version Ihrer Anwendung oder Bibliothek stattdessen das Flag --release.

--release

Kompilieren Sie DEX-Bytecode ohne Debug-Informationen. d8 enthält jedoch einige Informationen, die beim Generieren von Stacktraces und Logging von Ausnahmen verwendet werden.

Übergeben Sie dieses Flag, wenn Sie Bytecode für eine öffentliche Version kompilieren.

--output path

Geben Sie den gewünschten Pfad für die DEX-Ausgabe an. Standardmäßig gibt d8 die DEX-Datei(en) im aktuellen Arbeitsverzeichnis aus.

Wenn Sie den Pfad und Namen einer ZIP- oder JAR-Datei angeben, erstellt d8 die angegebene Datei und enthält die DEX-Ausgabedateien. Wenn Sie den Pfad zu einem vorhandenen Verzeichnis angeben, gibt d8 die DEX-Dateien in diesem Verzeichnis aus.

--lib android_sdk/platforms/api-level/android.jar Gib den Pfad zum android.jar deines Android SDK an. Dieses Flag ist erforderlich, wenn Bytecode kompiliert wird, der Java 8-Sprachfeatures verwendet.
--classpath path Geben Sie Klassenpfadressourcen an, die d8 möglicherweise zum Kompilieren der DEX-Dateien Ihres Projekts benötigt. Insbesondere müssen Sie bei d8 bestimmte Ressourcen angeben, wenn Sie Bytecode kompilieren, der Java 8-Sprachfeatures verwendet.
--min-api number Geben Sie das minimale API-Level an, das die DEX-Ausgabedateien unterstützen sollen.
--intermediate Übergeben Sie dieses Flag, um d8 darüber zu informieren, dass Sie nicht den vollständigen Satz des Java-Bytecodes Ihres Projekts kompilieren. Dieses Flag ist nützlich, wenn inkrementelle Builds ausgeführt werden. Anstatt optimierte DEX-Dateien zu kompilieren, die auf einem Gerät ausgeführt werden sollen, erstellt d8 Zwischen-DEX-Dateien und speichert sie im angegebenen Ausgabe- oder Standardpfad.

Wenn Sie DEX-Dateien kompilieren möchten, die auf einem Gerät ausgeführt werden sollen, schließen Sie dieses Flag aus und geben Sie den Pfad zu den DEX-Zwischenklassen als Eingabe an.

--file-per-class

Kompilieren Sie jede Klasse in separate DEX-Dateien.

Wenn Sie dieses Flag aktivieren, können Sie mehr inkrementelle Builds ausführen. Dazu kompilieren Sie nur die geänderten Klassen neu. Wenn Sie inkrementelle Builds mit dem Android-Gradle-Plug-in ausführen, ist diese Optimierung standardmäßig aktiviert.

Sie können dieses Flag nicht zusammen mit --main-dex-list verwenden.

--no-desugaring Java 8-Sprachfunktionen deaktivieren. Verwenden Sie dieses Flag nur, wenn Sie nicht vorhaben, Java-Bytecode zu kompilieren, der Java 8-Sprachfeatures verwendet.
--main-dex-list path

Geben Sie eine Textdatei mit den Klassen an, die d8 in die DEX-Hauptdatei aufnehmen soll. Sie hat in der Regel den Namen classes.dex. Wenn Sie mit diesem Flag keine Liste von Klassen angeben, garantiert d8 nicht, welche Klassen in der DEX-Hauptdatei enthalten sind.

Da das Android-System beim Start der Anwendung zuerst die DEX-Hauptdatei lädt, können Sie dieses Flag verwenden, um bestimmte Klassen beim Start zu priorisieren, indem Sie sie in die DEX-Hauptdatei kompilieren. Dies ist besonders nützlich, wenn Legacy-Multidex-Bibliothek unterstützt werden, da zur Laufzeit nur Klassen in der DEX-Hauptdatei verfügbar sind, bis die Legacy-Multidex-Bibliothek geladen ist.

Beachten Sie, dass jede DEX-Datei weiterhin das 64-K-Referenzlimit erfüllen muss. Geben Sie daher für die DEX-Hauptdatei nicht zu viele Klassen an, da sonst ein Kompilierungsfehler auftritt. Wenn Klassen mit --main-dex-list angegeben werden, schließt d8 standardmäßig nur diese Klassen in der DEX-Hauptdatei ein. Dies vereinfacht die Fehlerbehebung bei Problemen mit Klassen, die in der DEX-Hauptdatei fehlen. Wenn Sie den --release-Modus angeben, versucht d8, die Anzahl der in die Release-Version Ihrer App gepackten DEX-Dateien zu reduzieren. Dazu nimmt sie so viele andere Klassen wie möglich in die DEX-Hauptdatei auf, bis das Limit von 64 K erreicht ist.

Sie können dieses Flag nicht zusammen mit --file-per-class verwenden.

--pg-map file Verwenden Sie file als Zuordnungsdatei für die Verteilung.
--file-per-class-file

Erstellen Sie eine separate DEX-Datei pro .class-Eingabedatei.

Synthetische Klassen mit ihrer ursprünglichen Klasse beibehalten.

--desugared-lib file

Geben Sie die Konfiguration der gelöschten Bibliothek an.

file ist die Konfigurationsdatei der gelöschten Bibliothek im JSON-Format.

--main-dex-rules file Proguard behält Regeln für Klassen in der primären DEX-Datei bei.
--main-dex-list-output file Ausgabe der resultierenden DEX-Hauptliste in file.

--force-enable-assertions [:class_or_package_name...]

--force-ea [:class_or_package_name...]

javac-generierten Assertion-Code erzwingen.

--force-disable-assertions [:class_or_package_name...]

--force-da [:class_or_package_name...]

Erzwingt die Deaktivierung von javac-generiertem Assertion-Code. Dies ist die Standardbehandlung des javac-Assertion-Codes beim Generieren von DEX-Dateien.

--force-passthrough-assertions [:class_or_package_name...]

--force-pa [:class_or_package_name...]

Ändern Sie den von javac generierten Assertion-Code nicht. Dies ist die Standardbehandlung von javac-Assertion-Codes beim Generieren von class-Dateien.

--force-assertions-handler:handler method [:class_or_package_name...]

--force-ah:handler method [:class_or_package_name...]

Ändern Sie den von javac und kotlinc generierten Assertion-Code, um die Methode handler method bei jedem Assertion-Fehler aufzurufen, anstatt sie auszulösen. handler method wird als Klassenname gefolgt von einem Punkt und dem Methodennamen angegeben. Die Handler-Methode muss ein einzelnes Argument vom Typ java.lang.Throwable und den Rückgabetyp void haben.
--thread-count number of threads Geben Sie die Anzahl der Threads an, die für die Kompilierung verwendet werden sollen. Wenn keine Angabe erfolgt, basiert die Anzahl auf Heuristiken, wobei die Anzahl der Kerne berücksichtigt wird.
--map-diagnostics[ :type] from-level to-level Kartendiagnosen von type (Standardeinstellung) werden als from-level an to-level gemeldet, wobei from-level und to-level entweder „Info“, „Warnung“ oder „Fehler“ sind und der optionale type entweder der einfache oder voll qualifizierte Java-Typname einer Diagnose ist. Wenn type nicht angegeben ist, werden alle Diagnosen unter from-level zugeordnet. Schwerwiegende Compiler-Fehler können nicht zugeordnet werden.
--version Drucken Sie die Version von d8 aus, die Sie gerade verwenden.
--help Hilfetext zur Verwendung von d8 drucken.

Inkrementelle Builds ausführen

Um die Build-Geschwindigkeit während der Entwicklung zu verbessern, z. B. bei Continuous-Integration-Builds, weisen Sie d8 an, nur einen Teil des Java-Bytecodes Ihres Projekts zu kompilieren. Wenn Sie beispielsweise die Dexierung pro Klasse aktivieren, können Sie nur die Klassen neu kompilieren, die Sie seit dem vorherigen Build geändert haben.

Mit dem folgenden Befehl wird ein inkrementeller Build einiger Klassen ausgeführt und das Dexing pro Klasse aktiviert. Der Befehl gibt auch ein Ausgabeverzeichnis für den inkrementellen Build an.

d8 MainActivity.class R.class --intermediate --file-per-class --output ~/build/intermediate/dex

Wenn d8 einen inkrementellen Build ausführt, werden zusätzliche Informationen in der DEX-Ausgabe gespeichert. d8 verwendet diese Informationen später, um die Option --main-dex-list korrekt zu verarbeiten und DEX-Dateien während eines vollständigen Builds Ihrer Anwendung zusammenzuführen.

Bei der Verarbeitung von Lambda-Klassen in Java 8 erfasst d8 beispielsweise, welche Lambda-Klassen für jede Eingabeklasse erstellt werden. Wenn d8 während eines vollständigen Builds eine Klasse in der DEX-Hauptdatei enthält, prüft es die Metadaten, um sicherzustellen, dass alle für diese Klasse erstellten Lambda-Klassen auch in der DEX-Hauptdatei enthalten sind.

Wenn Sie bereits den gesamten Bytecode des Projekts über mehrere inkrementelle Builds in DEX-Dateien kompiliert haben, führen Sie einen vollständigen Build durch. Übergeben Sie dazu das Verzeichnis der DEX-Zwischendateien an d8, wie im folgenden Befehl gezeigt. Außerdem können Sie mit --main-dex-list die Klassen angeben, die d8 in die DEX-Hauptdatei kompilieren soll. Da es sich bei der Eingabe um eine Reihe von Dateien handelt, die bereits in DEX-Bytecode kompiliert sind, sollte dieser Build schneller abgeschlossen werden als ein sauberer Build.

d8 ~/build/intermediate/dex --release --main-dex-list ~/build/classes.txt --output ~/build/release/dex

Bytecode kompilieren, der Java 8-Sprachfeatures verwendet

Mit d8 können Sie über einen Kompilierungsprozess, der desugaring genannt wird, die Java 8-Sprachfeatures in Ihrem Code verwenden. Beim Desugaring werden diese nützlichen Sprachfunktionen in Bytecode umgewandelt, der auf der Android-Plattform ausgeführt werden kann.

Android Studio und das Android-Gradle-Plug-in enthalten Klassenpfad-Ressourcen, die d8 benötigt, um das Desugaring für Sie zu aktivieren. Wenn Sie d8 über die Befehlszeile verwenden, müssen Sie sie jedoch selbst einfügen.

Eine solche Ressource ist die android.jar aus deinem Android-Ziel-SDK. Diese Ressource enthält eine Reihe von Android-Plattform-APIs. Geben Sie den Pfad mit dem Flag --lib an.

Eine weitere Ressource ist der in Ihr Projekt kompilierte Java-Bytecode, den Sie derzeit nicht in DEX-Bytecode kompilieren, sondern andere Klassen in DEX-Bytecode kompilieren müssen.

Wenn Ihr Code beispielsweise Standard- und statische Schnittstellenmethoden verwendet, bei denen es sich um eine Java 8-Sprachfunktion handelt, müssen Sie mit diesem Flag den Pfad zum gesamten Java-Bytecode Ihres Projekts angeben, auch wenn Sie nicht den gesamten Bytecode in DEX-Bytecode kompilieren möchten. Das liegt daran, dass d8 diese Informationen benötigt, um den Code Ihres Projekts zu verstehen und Aufrufe an die Schnittstellenmethoden aufzulösen.

Im folgenden Codebeispiel wird ein inkrementeller Build einer Klasse ausgeführt, die auf eine Standardschnittstellenmethode zugreift:

d8 MainActivity.class --intermediate --file-per-class --output ~/build/intermediate/dex
--lib android_sdk/platforms/api-level/android.jar
--classpath ~/build/javac/debug