d8

d8 es una herramienta de línea de comandos que Android Studio y el complemento de Android para Gradle usan para compilar el código de bytes Java de tu proyecto en el código de bytes DEX que se ejecuta en dispositivos Android. d8 te permite usar las funciones del lenguaje Java 8 en el código de tu app.

d8 también se incluye como una herramienta independiente de las herramientas de compilación de Android 28.0.1 y versiones posteriores: android_sdk/build-tools/version/.

Uso general

d8 solo requiere una ruta de acceso al código de bytes Java compilado que deseas convertir en código de bytes DEX. Por ejemplo:

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

El código de bytes de entrada puede estar en cualquier combinación de contenedores o archivos *.class, como JAR, APK o ZIP. También puedes incluir archivos DEX para d8 a fin de combinarlos en la salida DEX, lo que resulta útil cuando se incluye la salida de una compilación incremental.

De forma predeterminada, d8 compila el código de bytes Java en archivos DEX optimizados e incluye información de depuración que puedes usar para depurar tu código durante el tiempo de ejecución. Sin embargo, puedes incluir marcas opcionales para realizar una compilación incremental, especificar las clases que se deben compilar en el archivo DEX principal y especificar rutas de acceso a los recursos adicionales que se necesitan para usar las funciones del lenguaje Java 8.

d8 path-to-input-files [options]

En la siguiente tabla, se describen las marcas opcionales que puedes usar con d8:

Opción Descripción
--debug

Compila el código de bytes DEX para incluir información de depuración, como tablas de símbolos de depuración.

Esta opción está habilitada de forma predeterminada. Para incluir información de depuración en tu código de bytes DEX, d8 espera que lo haga el código de bytes de entrada Java. Por ejemplo, si estás usando javac para compilar tu código, debes pasar la marca -g para incluir información de depuración en el código de bytes de salida Java.

Cuando compiles archivos DEX para la versión de actualización de tu app o biblioteca, usa la marca --release.

--release

Compila el código de bytes DEX sin información de depuración. Sin embargo, d8 incluye cierta información que se usa cuando se generan seguimientos de pila y excepciones de registro.

Pasa esta marca cuando compiles el código de bytes para una versión pública.

--output path

Especifica la ruta de acceso deseada para la salida DEX. De forma predeterminada, d8 genera los archivos DEX en el directorio de trabajo actual.

Si especificas una ruta de acceso y el nombre de un archivo ZIP o JAR, d8 crea el archivo especificado e incluye los archivos DEX de salida. Si especificas la ruta de acceso a un directorio existente, d8 genera los archivos DEX en ese directorio.

--lib android_sdk/platforms/api-level/android.jar Especifica la ruta de acceso a android.jar de tu SDK de Android. Esta marca es obligatoria cuando compilas el código de bytes que usa funciones del lenguaje Java 8.
--classpath path Especifica los recursos de ruta de clase que d8 puede requerir para compilar los archivos DEX de tu proyecto. En particular, d8 requiere que especifiques ciertos recursos cuando compiles el código de bytes que usa funciones del lenguaje Java 8.
--min-api number Especifica el nivel mínimo de API que quieres que admitan los archivos DEX de salida.
--intermediate Pasa esta marca para que d8 sepa que no estás compilando el conjunto completo del código de bytes Java de tu proyecto. Esta marca es útil cuando se realizan compilaciones incrementales. En lugar de compilar archivos DEX optimizados que esperas ejecutar en un dispositivo, d8 crea archivos DEX intermedios y los almacena en la salida o ruta predeterminada especificada.

Cuando quieras compilar archivos DEX para ejecutarlos en un dispositivo, excluye esta marca y especifica la ruta de acceso a las clases DEX intermedias como una entrada.

--file-per-class

Compila cada clase en archivos DEX separados.

la habilitación de esta marca te permite realizar más compilaciones incrementales volviendo a compilar solo las clases que cambiaron. Cuando realizas compilaciones incrementales con el complemento de Android para Gradle, esta optimización se habilita de forma predeterminada.

No puedes usar esta marca y especificar --main-dex-list al mismo tiempo.

--no-desugaring Inhabilita las funciones del lenguaje Java 8. Usa esta marca solamente si no tienes la intención de compilar el código de bytes Java que usa las funciones del lenguaje Java 8.
--main-dex-list path

Especifica un archivo de texto que enumera las clases que d8 debe incluir en el archivo DEX principal, que por lo general se denomina classes.dex. Cuando no especificas una lista de clases con esta marca, d8 no garantiza qué clases se incluyen en el archivo DEX principal.

Debido a que el sistema Android carga primero el archivo DEX principal cuando inicias tu app, puedes usar esta marca para priorizar ciertas clases al inicio compilándolas en el archivo DEX principal. Esto es particularmente útil cuando se admite multidex heredado porque solo las clases del archivo DEX principal están disponibles en el tiempo de ejecución hasta que se carga la biblioteca multidex heredada.

Ten en cuenta que cada archivo DEX aún debe satisfacer el límite de referencia de 64 K. Por lo tanto, no especifiques demasiadas clases para el archivo DEX principal; de lo contrario, obtendrás un error de compilación. De forma predeterminada, cuando se especifican clases con --main-dex-list, d8 incluye solo esas clases en el archivo DEX principal. Esto permite que los problemas relacionados con clases faltantes en el archivo DEX principal sean más fáciles de depurar. Si especificas el modo --release, d8 intenta reducir la cantidad de archivos DEX que se empaquetan en la versión de actualización de tu app incluyendo tantas otras clases en el archivo DEX principal como sea posible hasta alcanzar el límite de 64 K.

No puedes usar esta marca y especificar --file-per-class al mismo tiempo.

--pg-map file Usa file como archivo de asignación para la distribución.
--file-per-class-file

Genera un archivo DEX separado por archivo .class de entrada.

Conserva las clases sintéticas con su clase de origen.

--desugared-lib file

Especifica una configuración de biblioteca con expansión de sintaxis.

file es un archivo de configuración de la biblioteca con expansión de sintaxis en formato JSON.

--main-dex-rules file Proguard conserva las reglas para que las clases se coloquen en el archivo DEX principal.
--main-dex-list-output file Resultado de la lista de DEX principal en el archivo.

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

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

Habilita de manera forzosa el código de aserción que genera javac.

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

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

Inhabilita de manera forzosa el código de aserción que genera javac. Este es el control predeterminado del código de aserción javac cuando se generan archivos DEX.

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

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

No cambies el código de aserción que genera javac. Este es el control predeterminado del código de aserción javac cuando se generan archivos class.

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

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

Cambia el código de aserción que generan javac y kotlinc para invocar el método handler method con cada error de aserción en lugar de arrojarlo. handler method se especifica como un nombre de clase seguido de un punto y el nombre del método. El método del controlador debe tomar un solo argumento del tipo java.lang.Throwable y tener el tipo de datos que se muestra void.
--thread-count number of threads Especifica la cantidad de subprocesos que se usarán para la compilación. Si no se especifica, la cantidad se basará en la heurística y tendrá en cuenta la cantidad de núcleos.
--map-diagnostics[ :type] from-level to-level Diagnósticos de mapas de type (predeterminados de cualquier tipo) informados como from-level a to-level, en los que from-level y to-level son uno de los campos "información", "advertencia" o "error" y el type opcional es el nombre de tipo de Java simple o completamente calificado de un diagnóstico. Si no se especifica type, se asignan todos los diagnósticos en from-level. Ten en cuenta que no se pueden asignar errores graves del compilador.
--version Imprime la versión de d8 que estás usando actualmente.
--help Imprime el texto de ayuda para usar d8.

Cómo realizar compilaciones incrementales

Para mejorar las velocidades de compilación durante el desarrollo, como para las compilaciones de integración continua, puedes indicarle a d8 que compile solo un subconjunto del código de bytes Java de tu proyecto. Por ejemplo, si habilitas la conversión a DEX por clase, puedes volver a compilar solamente las clases que modificaste desde la compilación anterior.

El siguiente comando realiza una compilación incremental de algunas clases y habilita la conversión a DEX por clase. El comando también especifica un directorio de salida para la compilación incremental.

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

Cuando d8 realiza una compilación incremental, almacena información adicional en el resultado de DEX. Luego, d8 usa esa información para procesar correctamente la opción --main-dex-list y combinar los archivos DEX durante una compilación completa de tu app.

Por ejemplo, cuando se procesan clases lambda de Java 8, d8 hace un seguimiento de las clases lambda que se crean para cada clase de entrada. Durante una compilación completa, cuando d8 incluye una clase en el archivo DEX principal, consulta los metadatos para garantizar que todas las clases lambda creadas para esa clase también se incluyan en ese archivo.

Si ya compilaste todo el código de bytes de tu proyecto en archivos DEX en varias compilaciones incrementales, puedes realizar una compilación completa si pasas el directorio de archivos DEX intermedios a d8, como se muestra en el comando a continuación. Además, puedes especificar las clases que deseas que d8 compile en el archivo DEX principal mediante --main-dex-list. Debido a que la entrada es un conjunto de archivos que ya está compilado en un código de bytes DEX, esta compilación debería completarse más rápido que una compilación limpia.

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

Cómo compilar el código de bytes que usa las funciones del lenguaje Java 8

d8 te permite usar las funciones del lenguaje Java 8 en tu código a través de un proceso de compilación llamado expansión de sintaxis, que convierte estas útiles funciones de lenguaje en un código de bytes que se puede ejecutar en la plataforma de Android.

Android Studio y el complemento de Android para Gradle incluyen recursos de rutas de clase que d8 requiere para habilitar la expansión de sintaxis. Sin embargo, cuando usas d8 desde la línea de comandos, debes incluirlos tú mismo.

Uno de esos recursos es android.jar de tu SDK de Android objetivo. Este recurso incluye un conjunto de APIs de la plataforma de Android. Especifica su ruta con la marca --lib.

Otro recurso es el conjunto de código de bytes Java compilado en tu proyecto que actualmente no compilas en el código de bytes DEX, pero que necesitas para compilar otras clases en él.

Por ejemplo, si tu código usa métodos de interfaz estáticos y predeterminados, que es una función del lenguaje Java 8, necesitas usar esta marca para especificar la ruta de acceso a todo el código de bytes Java de tu proyecto, incluso si no pretendes compilarlo todo en un código de bytes DEX. Esto se debe a que d8 requiere esta información para comprender el código de tu proyecto y resolver las llamadas a los métodos de la interfaz.

En la siguiente muestra de código, se realiza una compilación incremental de una clase que accede a un método de interfaz predeterminado:

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