d8

d8 est un outil de ligne de commande utilisé par Android Studio et le plug-in Android Gradle pour compiler le bytecode Java de votre projet en bytecode DEX s'exécutant sur les appareils Android. d8 vous permet d'utiliser les fonctionnalités du langage Java 8 dans le code de votre application.

d8 est également inclus en tant qu'outil autonome dans Android Build Tools 28.0.1 et versions ultérieures : android_sdk/build-tools/version/.

Utilisation générale

d8 ne requiert qu'un chemin d'accès au bytecode Java compilé que vous souhaitez convertir en bytecode DEX. Par exemple :

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

Le bytecode d'entrée peut être n'importe quelle combinaison de fichiers ou de conteneurs *.class, tels que des fichiers JAR, APK ou ZIP. Vous pouvez également inclure des fichiers DEX pour d8 afin de les fusionner dans la sortie DEX. Cette opération peut s'avérer utile lorsque vous incluez la sortie d'une compilation incrémentielle.

Par défaut, d8 compile le bytecode Java en fichiers DEX optimisés et inclut des informations de débogage que vous pouvez utiliser pour déboguer votre code pendant l'exécution. Toutefois, vous pouvez inclure des indicateurs facultatifs pour effectuer une compilation incrémentielle, spécifier les classes à compiler dans le fichier DEX principal et spécifier les chemins d'accès aux ressources supplémentaires requises pour utiliser les fonctionnalités du langage Java 8.

d8 path-to-input-files [options]

Dans le tableau suivant, vous trouverez une description des indicateurs facultatifs que vous pouvez utiliser avec d8 :

Option Description
--debug

Compilez le bytecode DEX pour inclure des informations de débogage, telles que les tableaux de symboles de débogage.

Cette option est activée par défaut. Pour inclure des informations de débogage dans votre bytecode DEX, d8 s'attend à ce que le bytecode d'entrée Java contienne ces informations. Par exemple, si vous utilisez javac pour compiler votre code, vous devez transmettre l'indicateur -g pour inclure les informations de débogage dans le bytecode de sortie Java.

Lorsque vous compilez des fichiers DEX pour la version de votre application ou de votre bibliothèque, utilisez plutôt l'indicateur --release.

--release

Compilez le bytecode DEX sans les informations de débogage. Toutefois, d8 inclut des informations utilisées lors de la génération des traces de piles et des exceptions de journalisation.

Transmettez cet indicateur lorsque vous compilez le bytecode pour une version publique.

--output path

Indiquez le chemin d'accès souhaité pour la sortie DEX. Par défaut, d8 génère le ou les fichiers de sortie DEX dans le répertoire de travail actuel.

Si vous indiquez le chemin d'accès et le nom d'un fichier ZIP ou JAR, d8 crée le fichier spécifié et inclut les fichiers de sortie DEX. Si vous spécifiez le chemin d'accès à un répertoire existant, d8 génère les fichiers de sortie DEX dans ce répertoire.

--lib android_sdk/platforms/api-level/android.jar Indiquez le chemin d'accès au fichier android.jar de votre SDK Android. Cet indicateur est obligatoire lorsque vous compilez un bytecode utilisant des fonctionnalités du langage Java 8.
--classpath path Spécifiez les ressources "classpath" dont d8 peut avoir besoin pour compiler les fichiers DEX de votre projet. Plus spécifiquement, d8 exige que vous spécifiiez certaines ressources lorsque vous compilez le bytecode qui utilise les fonctionnalités du langage Java 8.
--min-api number Indiquez le niveau d'API minimal que les fichiers de sortie DEX doivent prendre en charge.
--intermediate Transmettez cet indicateur pour signaler à d8 que vous n'êtes pas en train de compiler l'ensemble complet du bytecode Java de votre projet. Cet indicateur est utile pour effectuer des compilations incrémentielles. Au lieu de compiler des fichiers DEX optimisés que vous prévoyez d'exécuter sur un appareil, d8 crée des fichiers DEX intermédiaires et les stocke au niveau du chemin de sortie spécifié ou du chemin par défaut.

Lorsque vous souhaitez compiler des fichiers DEX que vous voulez exécuter sur un appareil, excluez cet indicateur et définissez le chemin d'accès aux classes DEX intermédiaires comme entrée.

--file-per-class

Compilez chaque classe en fichiers DEX distincts.

Activer cet indicateur vous permet d'effectuer des compilations incrémentielles en recompilant uniquement les classes qui ont été modifiées. Lorsque vous effectuez des compilations incrémentielles à l'aide du plug-in Android Gradle, cette optimisation est activée par défaut.

Vous ne pouvez pas utiliser cette option si vous spécifiez également --main-dex-list.

--no-desugaring Désactivez les fonctionnalités du langage Java 8. N'utilisez cet indicateur que si vous n'avez pas l'intention de compiler un bytecode Java qui se sert des fonctionnalités du langage Java 8.
--main-dex-list path

Spécifiez un fichier texte qui liste les classes d8 à inclure dans le fichier DEX principal, généralement nommé classes.dex. Lorsque vous ne spécifiez pas de liste de classes à l'aide de cet indicateur, d8 ne garantit pas quelles classes sont incluses dans le fichier DEX principal.

Comme le système Android charge d'abord le fichier DEX principal au démarrage de votre application, vous pouvez utiliser cet indicateur pour hiérarchiser certaines classes au démarrage en les compilant dans le fichier DEX principal. Cela est particulièrement utile lorsque vous utilisez l'ancien multidex, car seules les classes du fichier DEX principal sont disponibles au moment de l'exécution jusqu'à ce que l'ancienne bibliothèque multidex soit chargée.

N'oubliez pas que chaque fichier DEX doit toujours respecter la limite de référence de 64 Ko. Veillez donc à ne pas spécifier trop de classes pour le fichier DEX principal, sinon vous obtiendrez une erreur de compilation. Par défaut, lorsque vous spécifiez des classes à l'aide de --main-dex-list, d8 n'inclut que ces classes dans le fichier DEX principal. L'objectif est de faciliter le débogage des problèmes liés aux classes manquantes dans le fichier DEX principal. Si vous spécifiez le mode --release, d8 tente de réduire le nombre de fichiers DEX inclus dans le package de la version de votre application, en incluant autant d'autres classes que possible dans le DEX principal, jusqu'à ce que la limite de 64 Ko soit atteinte.

Vous ne pouvez pas utiliser cette option si vous spécifiez également --file-per-class.

--pg-map file Utilisez file comme fichier de mappage pour la distribution.
--file-per-class-file

Générez un fichier DEX distinct par fichier .class d'entrée.

Conservez les classes synthétiques avec leur classe d'origine.

--desugared-lib file

Spécifiez une configuration de bibliothèque désucrée.

file est un fichier de configuration de bibliothèque au format JSON.

--main-dex-rules file Règles de conservation ProGuard pour les classes à placer dans le fichier DEX principal.
--main-dex-list-output file Affichez la liste DEX principale générée dans le fichier.

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

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

Forcez l'activation du code d'assertion généré par javac.

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

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

Forcez la désactivation du code d'assertion généré par javac. Il s'agit du traitement par défaut du code d'assertion javac lorsque vous générez des fichiers DEX.

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

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

Ne modifiez pas le code d'assertion généré par javac. Il s'agit du traitement par défaut du code d'assertion javac lorsque vous générez des fichiers class.

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

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

Modifiez le code d'assertion généré par javac et kotlinc pour appeler la méthode handler method avec chaque erreur d'assertion au lieu de la générer. La handler method est spécifiée en tant que nom de classe suivi d'un point et du nom de la méthode. La méthode du gestionnaire doit utiliser un seul argument de type java.lang.Throwable et doit inclure le type renvoyé void.
--thread-count number of threads Spécifiez le nombre de threads à utiliser pour la compilation. S'il n'est pas spécifié, ce nombre se base sur des méthodes heuristiques tenant compte du nombre de cœurs.
--map-diagnostics[ :type] from-level to-level Mappez les diagnostics de type (tout type par défaut) signalés comme étant from-level avec to-level, où from-level et to-level correspondent à une valeur "info", "avertissement" ou "erreur" et où le type facultatif est le nom de type Java simple ou complet d'un diagnostic. Si type n'est pas spécifié, tous les diagnostics de from-level sont mappés. Notez que les erreurs fatales du compilateur ne peuvent pas être mappées.
--version Affichez la version de d8 que vous utilisez actuellement.
--help Affichez le texte d'aide permettant d'utiliser d8.

Effectuer des compilations incrémentielles

Pour améliorer la vitesse de compilation pendant le développement, par exemple pour les compilations d'intégration continue, demandez à d8 de ne compiler qu'un sous-ensemble du bytecode Java de votre projet. Par exemple, si vous activez la conversion en DEX par classe, vous pouvez ne recompiler que les classes que vous avez modifiées depuis la compilation précédente.

La commande suivante effectue une compilation incrémentielle de quelques classes et active la conversion en DEX par classe. Cette commande spécifie également un répertoire de sortie pour la compilation incrémentielle.

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

Lorsque d8 effectue une compilation incrémentielle, il stocke des informations supplémentaires dans la sortie DEX. d8 utilise ensuite ces informations pour traiter correctement l'option --main-dex-list et fusionner les fichiers DEX lors de la compilation complète de votre application.

Par exemple, pendant qu'il traite des classes lambda Java 8, d8 garde la trace des classes lambda créées pour chaque classe d'entrée. Lors d'une compilation complète, quand d8 inclut une classe dans le fichier DEX principal, il consulte les métadonnées pour s'assurer que toutes les classes lambda créées pour cette classe sont également incluses dans le fichier DEX principal.

Si vous avez déjà compilé l'intégralité du bytecode de votre projet en fichiers DEX pour plusieurs compilations incrémentielles, vous pouvez effectuer une compilation complète en transmettant le répertoire de fichiers DEX intermédiaires à d8, comme indiqué dans la commande suivante. De plus, vous pouvez spécifier les classes que d8 doit compiler dans le fichier DEX principal à l'aide de --main-dex-list. Comme l'entrée est un ensemble de fichiers déjà compilés en bytecode DEX, cette compilation devrait se terminer plus rapidement qu'une compilation propre.

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

Compiler un bytecode utilisant les fonctionnalités du langage Java 8

d8 vous permet d'utiliser les fonctionnalités du langage Java 8 dans votre code via un processus de compilation appelé désucrage. Le désucrage convertit ces fonctionnalités de langage utiles en bytecode pouvant s'exécuter sur la plate-forme Android.

Android Studio et le plug-in Android Gradle incluent les ressources "classpath" dont d8 a besoin pour activer le désucrage. Toutefois, lorsque vous utilisez d8 à partir de la ligne de commande, vous devez les inclure vous-même.

Une de ces ressources est le fichier android.jar de votre SDK Android cible. Cette ressource inclut un ensemble d'API de la plate-forme Android. Spécifiez son chemin d'accès en utilisant l'indicateur --lib.

Une autre ressource est l'ensemble du bytecode Java compilé dans votre projet, que vous n'êtes pas en train de compiler en bytecode DEX, mais pour lequel vous devez compiler d'autres classes en bytecode DEX.

Par exemple, si votre code utilise les méthodes d'interface statiques et par défaut, une fonctionnalité du langage Java 8, vous devez utiliser cet indicateur pour spécifier le chemin d'accès de l'ensemble du bytecode Java de votre projet, même si vous n'avez pas l'intention de tout compiler en bytecode DEX. En effet, d8 a besoin de ces informations pour comprendre le code de votre projet et résoudre les appels aux méthodes d'interface.

L'exemple de code suivant effectue un build incrémentiel d'une classe qui accède à une méthode d'interface par défaut :

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