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. Ele 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
d8
é simples de usar e requer apenas um caminho para o bytecode Java compilado
que você quer converter em bytecode DEX, conforme mostrado abaixo.
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 o tempo de execução. No entanto, você pode incluir sinalizações opcionais
para, por exemplo, executar um build incremental, especificar classes que
precisam ser compiladas no arquivo DEX principal e especificar caminhos para
recursos adicionais necessários para uso de recursos da linguagem Java 8.
d8 path-to-input-files [options]
A tabela a seguir descreve as sinalizações opcionais que você pode usar com d8
.
Opção | Descrição |
---|---|
--debug
|
Compila o bytecode DEX incluindo 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
Ao compilar arquivos DEX para a versão de lançamento do seu app ou
biblioteca, use a sinalização |
--release
|
Compila o bytecode DEX sem informações de depuração. No entanto, d8
inclui algumas informações usadas ao gerar rastreamentos de pilha e
exceções de registros.
Transmita essa sinalização ao compilar bytecode para uma versão pública. |
--output path
|
Especifica 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, |
--lib android_sdk/platforms/api-level/android.jar
|
Especifica o caminho para android.jar do SDK do Android.
Essa sinalização é necessária ao compilar bytecodes que usam
recursos da linguagem Java 8.
|
--classpath path
|
Especifica os recursos do caminho de classe necessários para que d8 compile
os arquivos DEX do seu projeto. Em particular, d8 requer a
especificação de determinados recursos ao compilar bytecodes que usam
recursos da linguagem Java 8.
|
--min-api number
|
Especifica o nível mínimo de API com o qual você quer que os arquivos DEX de saída sejam compatíveis. |
--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: ao invés e compilar arquivos DEX otimizados
que você espera executar em um dispositivo, d8 cria arquivos DEX
intermediários e armazena-os na saída especificada ou no caminho padrão.
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
|
Compila cada classe em um arquivo DEX diferente. A ativação dessa sinalização permite que você execute mais builds incrementais, recompilando apenas as classes que mudaram. Ao executar builds 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 especificar
|
--no-desugaring
|
Desativa os 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
|
Especifica um arquivo de texto que lista classes que d8 precisa incluir no
arquivo DEX principal, normalmente denominado classes.dex . Ou
seja, quando você não especifica uma lista de classes usando essa sinalização,
d8 não garante quais classes serã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á compatibilidade com o legado multidex, porque somente as classes no arquivo DEX principal ficam disponíveis durante o tempo de execução até que a biblioteca de legado multidex seja carregada. Lembre-se de que cada arquivo DEX ainda precisa atender ao
limite de referência de 64 K. Portanto,
não especifique muitas classes para o arquivo DEX principal para que não haja um
erro de compilação. Por padrão, ao especificar classes usando
Não é possível usar essa sinalização ao especificar
|
--version
|
Exibe a versão do d8 que você está usando no momento.
|
--help
|
Exibe 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,
é possível instruir 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 a seguir 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 outras informações na
saída DEX, que são usadas posteriormente para o processamento certo da opção --main-dex-list
e combinação de arquivos DEX durante um build completo do app. Por exemplo, ao
processar classes lambda do Java 8, d8
mantém o controle de 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.
Caso já tenha compilado todo o bytecode do seu projeto em arquivos DEX
em vários builds incrementais, é possível fazer um build completo transmitindo o
diretório de arquivos DEX intermediários para d8
, conforme mostrado abaixo. Além disso, você
pode especificar as classes que quer que 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 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
d8
permite usar recursos da linguagem Java 8
no seu código por meio de um processo de compilação chamado simplificação, que converte esses
recursos de linguagem úteis em bytecode que possa 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 do projeto que
não está sendo compilado em bytecode DEX no momento, mas é necessário para compilar
outras classes no 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.
A amostra 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