d8

O d8 é uma ferramenta de linha de comando que o Android Studio e o Plug-in do Android para Gradle usam para compilar o bytecode Java do seu projeto no bytecode DEX executado em dispositivos Android. O d8 permite usar recursos da linguagem Java 8 no código do seu app.

d8 também está incluído como uma ferramenta autônoma nas Android Build Tools 28.0.1 e mais recentes do Android: android_sdk/build-tools/version/.

Uso geral

O d8 exige apenas um caminho para o bytecode Java compilado que você quer converter em bytecode DEX. Exemplo:

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

O bytecode de entrada pode estar em qualquer combinação de arquivos *.class ou contêineres, como arquivos JAR, APK ou ZIP. Você também pode incluir arquivos DEX para que d8 mescle esses arquivos na saída DEX, o que é útil ao incluir a saída de um build incremental.

Por padrão, d8 compila o bytecode Java em arquivos DEX otimizados e inclui informações de depuração que podem ser usadas para depurar seu código durante a execução. No entanto, você pode incluir sinalizações opcionais para executar um build incremental, especificar classes que precisam ser compiladas no arquivo DEX principal e especificar caminhos para recursos extras necessários para uso de recursos da linguagem Java 8.

d8 path-to-input-files [options]

A tabela abaixo descreve as sinalizações opcionais que você pode usar com d8:

Opção Descrição
--debug

Compila o bytecode DEX para incluir informações de depuração, como tabelas de símbolos de depuração.

Esta opção é ativada por padrão. Para incluir informações de depuração no bytecode DEX, o d8 espera que o bytecode Java de entrada contenha essas informações. Por exemplo, se você estiver usando javac para compilar seu código, será necessário transmitir a sinalização -g para incluir informações de depuração no bytecode Java de saída.

Ao compilar arquivos DEX para a versão de lançamento do seu app ou biblioteca, use a sinalização --release.

--release

Compile um bytecode DEX sem informações de depuração. No entanto, d8 inclui algumas informações usadas ao gerar stack traces e exceções de registros.

Transmita essa sinalização ao compilar bytecode para uma versão pública.

--output path

Especifique o caminho desejado para a saída DEX. Por padrão, d8 gera o(s) arquivo(s) DEX no diretório de trabalho atual.

Se você especificar um caminho e o nome de um arquivo ZIP ou JAR, d8 vai criar o arquivo especificado e incluir os arquivos DEX de saída. Se você especificar o caminho para um diretório existente, d8 vai gerar os arquivos DEX nesse diretório.

--lib android_sdk/platforms/api-level/android.jar Especifique o caminho para o android.jar do SDK do Android. Essa sinalização é necessária ao compilar bytecodes que usam recursos da linguagem Java 8.
--classpath path Especifique os recursos do caminho de classe necessários para que o d8 compile os arquivos DEX do seu projeto. Especificamente, d8 requer que você especifique determinados recursos ao compilar bytecode que usa recursos da linguagem Java 8.
--min-api number Especifique o nível mínimo de API que você quer que seja compatível com os arquivos DEX de saída.
--intermediate Transmita essa sinalização para informar d8 que você não está compilando o conjunto completo de bytecode Java do projeto. Essa sinalização é útil ao executar builds incrementais. Em vez de compilar arquivos DEX otimizados que você espera que sejam executados em um dispositivo, o d8 cria arquivos DEX intermediários e os armazena na saída ou no caminho padrão especificados.

Quando quiser compilar arquivos DEX que você pretende executar em um dispositivo, exclua essa sinalização e especifique o caminho para as classes DEX intermediárias como entrada.

--file-per-class

Compile cada classe em um arquivo DEX diferente.

A ativação dessa sinalização permite que você execute builds mais incrementais com a recompilação apenas das classes que foram alteradas. Ao executar compilações incrementais usando o Plug-in do Android para Gradle, essa otimização é ativada por padrão.

Não é possível usar essa sinalização ao também especificar --main-dex-list.

--no-desugaring Desative recursos da linguagem Java 8. Use essa sinalização apenas se você não pretende compilar bytecode Java que usa recursos da linguagem Java 8.
--main-dex-list path

Especifique um arquivo de texto que lista classes que o d8 precisa incluir no arquivo DEX principal, normalmente denominado classes.dex. Quando você não especifica uma lista de classes usando essa sinalização, o d8 não garante quais classes são incluídas no arquivo DEX principal.

Como o sistema Android carrega primeiro o arquivo DEX principal ao iniciar seu app, você pode usar essa sinalização para priorizar determinadas classes na inicialização, compilando-as no arquivo DEX principal. Isso é especialmente útil quando há suporte ao multidex legado, porque somente as classes no arquivo DEX principal ficam disponíveis durante a execução até que a biblioteca de multidex legado seja carregada.

Não esqueça que cada arquivo DEX ainda precisa atender ao limite de referência de 64 mil métodos. Portanto, não especifique muitas classes para o arquivo DEX principal, ou você vai encontrar um erro de compilação. Por padrão, ao especificar classes usando --main-dex-list, o d8 inclui apenas as classes no arquivo DEX principal. Isso facilita a depuração de problemas relacionados a classes ausentes no arquivo DEX principal. Se você especificar o modo --release, o d8 tentará reduzir o número de arquivos DEX empacotados na versão de lançamento do app incluindo o máximo possível de outras classes no arquivo DEX principal, até atingir o limite de 64 mil métodos.

Não é possível usar essa sinalização ao também especificar --file-per-class.

--pg-map file Use file como um arquivo de mapeamento para distribuição.
--file-per-class-file

Produza um arquivo DEX separado para cada arquivo .class de entrada.

Mantenha as classes sintéticas com a classe de origem.

--desugared-lib file

Especifique uma configuração de biblioteca de simplificação.

file é um arquivo de configuração da biblioteca simplificada no formato JSON.

--main-dex-rules file Use as regras de armazenamento do ProGuard para as classes no arquivo DEX principal.
--main-dex-list-output file Gere uma saída da lista principal de DEX resultante em file.

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

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

Force a ativação do código de declaração gerado por javac.

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

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

Desative à força o código de declaração gerado por javac. Esse é o processamento padrão do código de declaração javac ao gerar arquivos DEX.

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

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

Não mude o código de declaração gerado por javac. Esse é o processamento padrão do código de declaração javac ao gerar arquivos class.

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

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

Mude o código de declaração gerado por javac e kotlinc para invocar o método handler method com cada erro de declaração, em vez de gerá-lo. O handler method é especificado como um nome de classe seguido de um ponto e do nome do método. O método de gerenciador precisa usar um único argumento do tipo java.lang.Throwable e ter o tipo de retorno void.
--thread-count number of threads Especifique o número de linhas de execução a serem usadas para compilação. Se não for especificado, o número vai ser baseado na heurística, considerando o número de núcleos.
--map-diagnostics[ :type] from-level to-level Mapeie o diagnóstico de type (qualquer um) informado como from-level para to-level, em que from-level e to-level são "info" e "warning" (aviso) ou "error" (erro), e o type opcional é o nome do tipo de Java simples ou totalmente qualificado de um diagnóstico. Se type não for especificado, todos os diagnósticos em from-level vão ser mapeados. Os erros fatais do compilador não podem ser mapeados.
--version Mostre a versão do d8 que você está usando no momento.
--help Mostre o texto de ajuda para usar d8.

Executar builds incrementais

Para melhorar as velocidades de compilação durante o desenvolvimento, como para builds de integração contínua, instrua d8 para compilar apenas um subconjunto do bytecode Java do seu projeto. Por exemplo, se você ativar a dexação por classe, será possível recompilar somente as classes que você modificou desde o build anterior.

O comando abaixo executa um build incremental de algumas classes e ativa a dexação por classe. O comando também especifica um diretório de saída para o build incremental.

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

Quando d8 executa um build incremental, ele armazena mais informações na saída DEX. Mais tarde, o d8 usará essas informações para processar corretamente a opção --main-dex-list e mesclar arquivos DEX durante um build completo do app.

Por exemplo, ao processar classes lambda do Java 8, o d8 monitora quais classes lambda são criadas para cada classe de entrada. Em um build completo, quando d8 inclui uma classe no arquivo DEX principal, ele consulta os metadados para garantir que todas as classes lambda criadas para essa classe também sejam incluídas no arquivo DEX principal.

Se você já tiver compilado todo o bytecode do seu projeto em arquivos DEX em vários builds incrementais, realize um build completo transmitindo o diretório de arquivos DEX intermediários para d8, conforme mostrado no comando abaixo. Além disso, você pode especificar as classes para que o d8 compile no arquivo DEX principal usando --main-dex-list. Como a entrada é um conjunto de arquivos que já está compilado no bytecode DEX, esse build provavelmente vai ser concluído mais rapidamente que um build limpo.

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

Compilar bytecode que usa recursos da linguagem Java 8

O d8 permite usar recursos da linguagem Java 8 no seu código com um processo de compilação chamado simplificação, que converte esses recursos de linguagem úteis em um bytecode que pode ser executado na plataforma Android.

O Android Studio e o Plug-in do Android para Gradle incluem recursos de caminho de classe que d8 exige para ativar esse processo para você. No entanto, ao usar d8 na linha de comando, você mesmo precisa incluí-los.

Um desses recursos é o android.jar do SDK do Android de destino. Esse recurso inclui um conjunto de APIs da plataforma Android, e o caminho precisa ser especificado usando a sinalização --lib.

Outro recurso é o conjunto de bytecode Java compilado no projeto que você não está compilando em bytecode DEX, mas que é necessário para compilar outras classes em bytecode DEX.

Por exemplo, caso seu código use métodos de interface padrão e estática (link em inglês), que é um recurso da linguagem Java 8, use essa sinalização para especificar o caminho para todo o bytecode Java do projeto, mesmo que não pretenda compilar tudo em bytecode DEX. Isso porque d8 precisa dessas informações para entender o código do projeto e resolver chamadas para os métodos da interface.

O exemplo de código a seguir executa um build incremental de uma classe que acessa um método de interface padrão:

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