
Nesta postagem, falaremos sobre o tempo de execução do Android. Em particular, tentarei resumir de forma breve, mas sucinta, como ART e Dalvik diferem e como as ferramentas de desenvolvimento do Android melhoraram com o tempo. O tópico claramente não é novo, mas espero que seja útil para aqueles que estão apenas começando a se aprofundar nele. Quem se importa - bem-vindo ao gato.
Máquina virtual
Primeiro, vamos ver como a JVM difere do DVM.
Java Virtual Machine é uma máquina virtual capaz de executar bytecode Java independentemente da plataforma subjacente. É baseado no princípio “Escreva uma vez, execute em qualquer lugar”. O bytecode Java pode ser executado em qualquer máquina capaz de suportar o JVM.
O compilador Java converte arquivos .java em arquivos de classe (bytecode). O bytecode é passado para a JVM, que o compila em código de máquina para execução diretamente na CPU.
Recursos JVM:
- Possui uma arquitetura de pilha: uma pilha é usada como uma estrutura de dados onde os métodos são colocados e armazenados. Funciona no esquema LIFO ou “Último a entrar - Primeiro a sair” ou “Último a entrar, primeiro a sair”.
- Só pode executar arquivos de classe.
- Usa um compilador JIT.
A Dalvik Virtual Machine (DVM) é uma máquina virtual Java desenvolvida e escrita por Dan Bornstein e outros como parte da plataforma móvel Android.
Podemos dizer que Dalvik é o ambiente para a execução de componentes do sistema operacional Android e aplicativos personalizados. Cada processo é executado em seu próprio espaço de endereço isolado. Quando o usuário inicia o aplicativo (ou o sistema operacional inicia um de seus componentes), o núcleo da máquina virtual Dalvik (Zygote Dalvik VM) cria um processo separado e protegido em memória compartilhada, no qual a VM é implantada diretamente como um ambiente para iniciar o aplicativo. Em outras palavras, por dentro, o Android parece um conjunto de máquinas virtuais Dalvik, cada uma rodando um aplicativo.
Recursos do DVM:
- Usa uma arquitetura baseada em registro: a estrutura de dados onde os métodos são colocados é baseada nos registros do processador. Devido à ausência de operações POP e PUSH, os comandos em uma máquina virtual registrada são executados mais rapidamente do que comandos semelhantes em uma máquina virtual de pilha.
- Executa bytecode de formato nativo: Android dexer (falaremos sobre isso a seguir) converte arquivos de classe para o formato .dex, otimizado para execução na VM Dalvik. Ao contrário de um arquivo de classe, um arquivo dex contém várias classes de uma vez.

Você pode ler mais sobre a arquitetura DVM aqui .
Android Dexer
Os desenvolvedores Android sabem que o processo de conversão de bytecode Java em bytecode .dex para Android Runtime é uma etapa fundamental na criação de um APK. O compilador dex funciona principalmente “nos bastidores” no desenvolvimento de aplicativos do dia-a-dia, mas afeta diretamente o tempo de construção do aplicativo, o tamanho do arquivo .dex e o desempenho do tempo de execução.
Como já mencionado, o próprio arquivo dex contém várias classes de uma vez. Linhas duplicadas e outras constantes usadas em vários arquivos de classe são incluídas apenas para economizar espaço. O bytecode Java também é convertido em um conjunto de instruções alternativo usado pelo DVM. O arquivo dex descompactado é geralmente um pouco menor do que o arquivo Java compactado (JAR) obtido dos mesmos arquivos .class.
Inicialmente, os arquivos de classe foram convertidos em arquivos dex usando o compilador DX integrado. Mas a partir do Android Studio 3.1 em diante, o D8 se tornou o compilador padrão . Comparado com o compilador DX, o D8 compila mais rápido e produz arquivos dex menores, enquanto fornece melhor desempenho do aplicativo em tempo de execução. O bytecode dex obtido desta forma é reduzido usando o utilitário ProGuard de código aberto . Como resultado, obtemos o mesmo arquivo dex, mas menor. Este arquivo dex é então usado para construir o apk e finalmente para implantar em um dispositivo Android.

Mas atrás do D8 em 2018 veio o R8, que, na verdade, é o mesmo D8, apenas com acréscimos.
Ao trabalhar com o Android Studio 3.4 e o plugin Android Gradle 3.4.0 ou superior, o Proguard não é mais usado para otimizar o código em tempo de compilação. Em vez disso, o plug-in funciona por padrão com o R8, que reduz o código, a otimização e a ofuscação. Embora R8 ofereça apenas um subconjunto da funcionalidade fornecida pelo Proguard, ele permite que você faça a conversão de bytecode Java em bytecode dex uma vez, o que reduz ainda mais o tempo de construção.

R8 e redução de código
Normalmente, os aplicativos usam bibliotecas de terceiros, como Jetpack, Gson, Google Play Services. Quando usamos uma dessas bibliotecas, geralmente o aplicativo usa apenas uma pequena parte de cada biblioteca individual. Sem a redução do código, todo o código da biblioteca é armazenado em seu aplicativo.
Acontece que os desenvolvedores usam código detalhado para melhorar a legibilidade e a manutenção de um aplicativo. Por exemplo, nomes de variáveis significativos e um padrão de design podem ser usados para ajudar outras pessoas a entender o código mais facilmente. Mas os modelos tendem a gerar mais código do que o necessário.
É aqui que o R8 vem ao resgate. Ele pode reduzir significativamente o tamanho do aplicativo, otimizando o tamanho até mesmo do código que é realmente usado pelo aplicativo.
Como exemplo, abaixo estão os números do relatório Shrinking Your App with R8 , que foi apresentado no Android Dev Summit '19:

E é assim que se parecia a comparação da eficácia do R8 no estágio de lançamento beta (retirado do blog de desenvolvedores Android fonte ):



Mais detalhes podem ser encontrados na documentação do escritório e relatório .
ART vs DVM no Android
DVM foi projetado especificamente para dispositivos móveis e foi usado como uma
máquina virtual para executar aplicativos Android até Android 4.4 Kitkat.
A partir desta versão, o ART foi introduzido como um tempo de execução e, no Android 5.0 (Lollipop), o ART substituiu completamente o Dalvik.
A principal diferença clara entre ART e DVM é que ART usa compilação AOT, enquanto DVM usa compilação JIT. Não muito tempo atrás, o ART começou a usar um híbrido de AOT e JIT. Vamos dar uma olhada nisso.
DVM
- Usa compilação JIT: sempre que o aplicativo é iniciado,
- a parte do código necessária para executar o aplicativo é compilada. O resto do código é compilado dinamicamente. Isso retarda o início e a operação dos aplicativos, mas reduz o tempo de instalação.
- , .
- , DVM, , , ART.
- , CPU.
- Dalvik “” 4.4.

ART
- AOT , . , .
- , .
- AOT , DVM.
- , - .
- Coleta de lixo ou coleta de lixo aprimorada. Ao usar Dalvik, os coletores de lixo tinham que fazer 2 passagens no heap, o que levava a uma UX pobre. No caso do ART, essa situação não existe: ele limpa a pilha uma vez para consolidar a memória.

E um pequeno diagrama de Dalvik vs ART:

JIT + AOT em ART
O Android Runtime (ART) desde o Android 7 inclui um compilador JIT com perfil de código. O compilador JIT complementa o compilador AOT e melhora o desempenho do tempo de execução, economiza espaço em disco e acelera as atualizações de aplicativo e sistema.
Isso acontece da seguinte maneira: em

vez de executar a compilação AOT de cada aplicativo durante a fase de instalação, ele executa o aplicativo sob o controle de uma máquina virtual usando um compilador JIT (quase o mesmo que no Android <5.0), mas mantém o controle de qual seções do código do aplicativo são executadas com mais freqüência. Essas informações são então usadas para AOT compilar essas seções de código. A última operação é realizada apenas quando o smartphone está inativo durante o carregamento.
Em termos simples, agora duas abordagens completamente diferentes funcionam juntas, o que oferece suas vantagens:
- compilação mais eficiente - quando o aplicativo é iniciado em tempo real, o compilador tem a oportunidade de aprender muito mais sobre seu trabalho do que realizar análises estáticas e, como resultado, métodos de otimização mais adequados são aplicados para cada situação;
- preservação de RAM e memória permanente - o código de bytes é mais compacto do que o código de máquina e, se você executar a compilação AOT de apenas algumas seções do aplicativo e não compilar aplicativos que o usuário não usa, pode economizar significativamente o espaço de memória NAND;
- aumento dramático na instalação e velocidade de primeira inicialização após a atualização do sistema - sem compilação AOT, sem demora.
Leia mais sobre a implementação do compilador JIT em ART aqui .
Conclusão
Neste artigo, tentei dar uma olhada nas principais diferenças entre Dalvik e ART e, de modo geral, dar uma olhada em como o Android melhorou suas ferramentas de desenvolvimento com o tempo.
O ART ainda está em desenvolvimento com novos recursos sendo adicionados para melhorar a experiência de usuários e desenvolvedores.
Se foi útil, deixe-me saber nos comentários.