Compilar com o Jack (AOSP 6.0 a 8.1)

O Jack é o conjunto de ferramentas padrão de build para as versões 6.0 a 8.1 do Android.

Ele era uma cadeia de ferramentas do Android que compilava fonte Java em bytecode dex do Android. Você não precisa fazer nada diferente para usar o Jack, apenas usar seus comandos makefile padrão para compilar a árvore ou o projeto. O Android 8.1 é a última versão que usa o Jack.

Sobre o Jack

O Jack funciona como mostrado na Figura 1.

Visão geral do Jack.

Figura 1. Visão geral do Jack.

Formato da biblioteca do Jack

O Jack tem o próprio formato de arquivo .jack, que contém o código dex pré-compilado para a biblioteca, possibilitando uma compilação mais rápida (pré-dex).

Conteúdo do arquivo da biblioteca do Jack.

Figura 2. Conteúdo do arquivo da biblioteca do Jack.

Jill

Como mostrado na figura a seguir, a ferramenta Jill converte as .jar bibliotecas existentes para o novo formato.

Fluxo de trabalho para importar uma biblioteca .jar existente.

Figura 3. Fluxo de trabalho para importar uma biblioteca .jar já existente.

Servidor de compilação do Jack

A primeira vez que o Jack é usado, ele abre um servidor de compilação Jack local no seu computador, que:

  • traz um aumento de velocidade intrínseco, porque evita a abertura de um novo host JRE JVM, o carregamento do código do Jack, a inicialização do Jack e o aquecimento do JIT a cada compilação. Ele também oferece tempos de compilação muito bons durante pequenas compilações (por exemplo, no modo incremental);
  • é uma solução de curto prazo para controlar o número de compilações Jack paralelas. O servidor evita sobrecarregar seu computador (problema de memória ou de disco) porque limita o número de compilações paralelas.

O servidor do Jack é desativado após um período de inatividade sem nenhuma compilação. Ele usa duas portas TCP na interface do localhost e não está disponível externamente. Todos os parâmetros (número de compilações paralelas, tempo limite, número de portas etc.) podem ser modificados editando o arquivo $HOME/.jack.

Arquivo $HOME/.jack

O arquivo $HOME/.jack contém as seguintes configurações para as variáveis do servidor do Jack em uma sintaxe bash completa:

  • SERVER=true ativa o recurso de servidor do Jack.
  • SERVER_PORT_SERVICE=8072 define o número da porta TCP do servidor para fins de compilação.
  • SERVER_PORT_ADMIN=8073 define o número da porta TCP do servidor para fins administrativos.
  • SERVER_COUNT=1 não é usado.
  • SERVER_NB_COMPILE=4 define o número máximo de compilações paralelas permitidas. SERVER_TIMEOUT=60 define o número de segundos de inatividade que o servidor precisa aguardar sem nenhuma compilação antes de se desligar. SERVER_LOG=${SERVER_LOG:=$SERVER_DIR/jack-$SERVER_PORT_SERVICE.log} define o arquivo em que os registros do servidor são gravados. Por padrão, essa variável pode ser sobrecarregada por uma variável de ambiente.
  • JACK_VM_COMMAND=${JACK_VM_COMMAND:=java} define o comando padrão usado para iniciar uma JVM no host. Por padrão, essa variável pode ser sobrecarregada pela variável de ambiente.

Resolver problemas de compilação do Jack

Problema Ação
Seu computador deixa de responder durante a compilação ou você percebe que as compilações do Jack falham com Erro de falta de memória Reduza o número de compilações simultâneas do Jack editando $HOME/.jack e mudando SERVER_NB_COMPILE para um valor mais baixo.
As compilações estão falhando, apresentando o erro Não é possível iniciar o servidor em segundo plano A causa mais provável é que as portas TCP já estão sendo usadas no seu computador. Mude as portas editando $HOME/.jack (as variáveis SERVER_PORT_SERVICE e SERVER_PORT_ADMIN). Para resolver a situação, desative o servidor de compilação do Jack editando $HOME/.jack e mudando SERVER para false. Infelizmente, isso diminui significativamente a velocidade da sua compilação e pode obrigar você a abrir make -j com controle de carga (opção -l de make).
A compilação é interrompida sem qualquer progresso Para resolver a situação, elimine o servidor em segundo plano do Jack usando jack-admin kill-server e remova os diretórios temporários contidos em jack-$USER do seu diretório temporário (/tmp ou $TMPDIR).

Encontrar o registro do Jack

Se você executar um comando make com um destino dist, o registro do Jack estará localizado em $ANDROID_BUILD_TOP/out/dist/logs/jack-server.log. Caso contrário, você poderá encontrar o log executando jack-admin server-log. Em caso de falhas do Jack reproduzíveis, veja um log mais detalhado definindo a seguinte variável:

export ANDROID_JACK_EXTRA_ARGS="--verbose debug --sanity-checks on -D sched.runner=single-threaded"

Use comandos makefile padrão para compilar a árvore (ou seu projeto) e anexar a saída padrão e o erro. Para remover os logs de criação detalhados, execute:

unset ANDROID_JACK_EXTRA_ARGS

Limitações do Jack

Por padrão, o servidor do Jack pode ser usado por apenas um usuário em um computador. Para aceitar mais usuários, selecione diferentes números de porta para cada um deles e ajuste o SERVER_NB_COMPILE corretamente. Você também pode desativar o servidor do Jack configurando SERVER=false em $HOME/.jack. A compilação do CTS é lenta devido à integração atual do vm-tests-tf. As ferramentas de manipulação de bytecode (como o JaCoCo) não têm suporte.

Usar o Jack

O Jack tem suporte à linguagem de programação Java 1.7 e integra os recursos descritos abaixo.

Pré-dexação

Ao gerar um arquivo de biblioteca do Jack, o .dex da biblioteca é gerado e armazenado dentro do arquivo de biblioteca .jack como um pré-dex. Durante a compilação, o Jack reutiliza o pré-dex de cada biblioteca. Todas as bibliotecas são pré-dexadas.

Bibliotecas do Jack com pré-dex.

Figura 4. Bibliotecas do Jack com pré-dex.

O Jack não reutiliza a pré-dexação da biblioteca quando a redução, a ofuscação ou o reempacotamento são usados na compilação.

Compilação incremental

Compilação incremental significa que somente os componentes modificados desde a última compilação (e as dependências deles) são recompilados. A compilação incremental pode ser significativamente mais rápida do que uma compilação completa quando as mudanças se limitam a um conjunto de componentes.

A compilação incremental é desativada por padrão. A desativação é automática quando a redução, o ofuscamento, o reempacotamento ou o legado de multidex está ativado. Para ativar builds incrementais, adicione a linha abaixo ao arquivo Android.mk do projeto que você quer criar de forma incremental:

LOCAL_JACK_ENABLED := incremental

Redução e ofuscação

O Jack usa arquivos de configuração do ProGuard para permitir a redução e a ofuscação.

Entre as opções comuns estão as seguintes:

  • @
  • -include
  • -basedirectory
  • -injars
  • -outjars (é permitido apenas 1 jar de saída)
  • -libraryjars
  • -keep
  • -keepclassmembers
  • -keepclasseswithmembers
  • -keepnames
  • -keepclassmembernames
  • -keepclasseswithmembernames
  • -printseeds

Entre as opções de redução está a seguinte:

  • -dontshrink

Entre as opções de ofuscação estão as seguintes:

  • -dontobfuscate
  • -printmapping
  • -applymapping
  • -obfuscationdictionary
  • -classobfuscationdictionary
  • -packageobfuscationdictionary
  • -useuniqueclassmembernames
  • -dontusemixedcaseclassnames
  • -keeppackagenames
  • -flattenpackagehierarchy
  • -repackageclasses
  • -keepattributes
  • -adaptclassstrings

Entre as opções ignoradas estão as seguintes:

  • -dontoptimize (Jack não otimiza)
  • -dontpreverify (Jack não faz a pré-verificação)
  • -skipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclasses
  • -dontskipnonpubliclibraryclassmembers
  • -keepdirectories
  • -target
  • -forceprocessing
  • -printusage
  • -whyareyoukeeping
  • -optimizations
  • -optimizationpasses
  • -assumenosideeffects
  • -allowaccessmodification
  • -mergeinterfacesaggressively
  • -overloadaggressively
  • -microedition
  • -verbose
  • -dontnote
  • -dontwarn
  • -ignorewarnings
  • -printconfiguration
  • -dump

Reempacotamento

O Jack usa arquivos de configuração jarjar para realizar o reempacotamento. Embora o Jack seja compatível com os tipos de regra "rule", ele não é compatível com os tipos de regra "zap" ou "keep".

Compatibilidade com multidex

O Jack oferece suporte nativo e legado com multidex. Como os arquivos dex estão limitados a 65 mil métodos, os apps com mais do que isso precisam ser divididos em vários arquivos dex. Para mais detalhes, consulte Ativar multidex para apps com mais de 64 mil métodos.