A máquina virtual Dalvik foi um componente-chave do sistema operacional Android, responsável por executar aplicativos até a versão 4.4 KitKat. Desenvolvida por Dan Bornstein, esta VM baseada em registradores substituiu o conceito de JVM padrão e permitiu otimizar a inicialização de aplicativos em dispositivos móveis com RAM limitada. De acordo com Google, 2024, o Dalvik garantia a compatibilidade de aplicativos através da compilação JIT, convertendo bytecode DEX em instruções de máquina diretamente durante a execução.
Principais pontos
Dalvik é uma máquina virtual com arquitetura de registradores, criada especificamente para a plataforma Android. O desenvolvimento começou em 2005 pela empresa de Dan Bornstein, e em 2007 o projeto foi adquirido pelo Google. A primeira versão comercial do Dalvik apareceu com o lançamento do Android 1.0 em 2008.
Ao contrário da Máquina Virtual Java padrão (JVM), o Dalvik não executa bytecode Java. O compilador Java converte o código fonte em arquivos class, e então o utilitário dx os traduz para o formato Dalvik Executable (DEX). Este formato é mais compacto que arquivos class: um aplicativo de 10 MB no formato class ocupa aproximadamente 6–7 MB em DEX.
Dan Bornstein escreveu o Dalvik como um projeto para sistemas operacionais com recursos limitados. O nome foi tirado da vila islandesa de Dalvík. O Google escolheu o Dalvik em vez da JVM devido a restrições de licenciamento e à necessidade de otimização profunda para processadores móveis com arquitetura ARM. O sistema rapidamente ganhou popularidade: em 2012, mais de 500 milhões de dispositivos Android rodavam Dalvik.
Cada aplicativo Android é executado em um processo separado com sua própria instância da VM Dalvik. Isso garante o isolamento de dados e a proteção contra código malicioso no nível do sistema operacional. Esta abordagem combina as vantagens da virtualização com o sandbox do Linux — malware em um aplicativo não pode afetar processos vizinhos.
A arquitetura baseada em registradores do Dalvik difere fundamentalmente da arquitetura baseada em pilha da JVM. Em vez de operações no topo da pilha, o Dalvik opera com registradores — células virtuais dentro da VM. Cada instrução contém os endereços dos registradores operando, o que reduz o número de instruções por operação.
A máquina de pilha JVM usa instruções como push, pop e add — para somar dois números são necessárias três instruções. Dalvik resolve a mesma tarefa com uma instrução add-int com três registradores. De acordo com o Android Open Source Project, a arquitetura de registradores do DEX reduz o tamanho do bytecode em média 30% em comparação com o formato de pilha class.
Um arquivo DEX (Dalvik Executable) contém uma representação compactada de todas as classes do aplicativo. O cabeçalho do arquivo inclui uma soma de verificação, tamanhos de seção e deslocamentos. As principais seções são os pools de strings, tipos, protótipos de métodos, campos e o próprio bytecode. Um único arquivo DEX pode armazenar até 65.536 métodos (a limitação foi removida com a introdução do multi-dex no Android 5.0).
O utilitário dx, incluído no Android SDK Build Tools, é usado para converter arquivos class em DEX. Exemplo de comando: dx --dex --output=classes.dex myapp.jar. Projetos modernos usam D8, o sucessor do dx com otimização melhorada e suporte para recursos Java 8+.
# Convertendo JAR para DEX usando dx
dx --dex --output=classes.dex myapp.jar
# Versão moderna via D8
d8 --lib android.jar --output dex/ myapp.jar
O processo Zygote é um elemento crucial da arquitetura Dalvik. Quando o sistema inicia, o Zygote carrega todas as classes do SDK Android, abre bibliotecas compartilhadas e cria um pool de recursos pré-carregados. Quando um usuário abre um aplicativo, o sistema bifurca o processo Zygote (fork), criando uma nova instância da VM Dalvik com um framework já inicializado. Isso reduz o tempo de inicialização do aplicativo de ~2–3 segundos para 300–500 milissegundos.
JIT (Just-In-Time) é uma tecnologia para compilar bytecode em instruções de máquina diretamente durante a execução do aplicativo. No Dalvik, o compilador JIT analisa o código DEX em execução, identifica métodos frequentemente usados (hot) e os compila em código nativo para a CPU.
A escolha do JIT em vez da compilação completa Ahead-Of-Time (AOT) nas primeiras versões do Android foi deliberada. Dispositivos móveis tinham armazenamento flash limitado (4–16 GB) — pré-compilar todos os aplicativos teria ocupado espaço significativo. Além disso, a memória ROM nos primeiros dispositivos era mais lenta que a RAM, e a leitura de código pré-compilado poderia reduzir o desempenho.
Quando um aplicativo é iniciado, o Dalvik começa a interpretar o bytecode DEX. Um perfilador especial rastreia quais métodos são chamados com mais frequência. Após exceder um limite (tipicamente ~200 chamadas), o compilador JIT converte o método em código de máquina e o armazena em cache na RAM. Chamadas subsequentes usam a versão já compilada sem recompilação.
// Exemplo de um método hot que o JIT compilará
public class Calculator {
public int sumArray(int[] arr) {
int total = 0;
for (int i = 0; i < arr.length; i++) {
total += arr[i];
}
return total;
}
}
De acordo com o Google I/O 2013, a introdução do JIT no Android 2.2 Froyo acelerou a execução de aplicativos em média 2–5 vezes em comparação com a interpretação pura. No entanto, o JIT adiciona latência no primeiro lançamento: um aplicativo precisa de 3 a 10 segundos para aquecer e compilar métodos hot. Após o aquecimento, o desempenho se estabiliza em um nível próximo ao código nativo.
Dalvik difere da JVM em vários aspectos fundamentais. Primeiro — arquitetura: JVM é baseada em pilha, Dalvik é baseada em registradores. Segundo — formato de bytecode: JVM usa arquivos class, Dalvik usa DEX. Terceiro — gerenciamento de memória: Dalvik é otimizado para a RAM limitada de dispositivos móveis.
Ambas as abordagens têm seus pontos fortes. A JVM baseada em pilha requer menos espaço para armazenar instruções — cada instrução é mais curta porque os operandos são implicitamente retirados da pilha. O Dalvik baseado em registradores executa menos instruções por operação, o que economiza tempo de CPU e reduz o consumo de energia. Para dispositivos móveis alimentados por bateria, isso é crítico.
| Parâmetro | Dalvik | JVM |
|---|---|---|
| Arquitetura | Baseada em registradores | Baseada em pilha |
| Bytecode | DEX | class |
| Compilação | JIT (Android 2.2+) | JIT / AOT |
| Otimização | Baixo consumo de energia | Alta compatibilidade |
| Isolamento | Através de processos Linux | Através de ClassLoader |
A escolha do Dalvik em vez da JVM também foi motivada pelo licenciamento. A Oracle detém os direitos do Java SE e da JVM, e o Google buscava evitar taxas de licenciamento. Criar sua própria VM com um formato de bytecode alternativo permitiu que o Android se desenvolvesse independentemente da Oracle. Esta disputa se transformou em uma longa batalha legal, Oracle vs Google (2010–2021), que terminou a favor do Google.
DEX (Dalvik Executable) é um formato binário contendo o código compilado de um aplicativo Android. Cada arquivo DEX começa com um cabeçalho, seguido por seções: constantes de string (string_ids), tipos (type_ids), protótipos de métodos (proto_ids), campos (field_ids), métodos (method_ids), definições de classe (class_defs) e uma área de dados.
O utilitário dx converte arquivos class Java em um ou mais arquivos DEX. O algoritmo inclui desduplicação de constantes — strings ou tipos idênticos são armazenados uma vez e referenciados por índice. Isso reduz significativamente o tamanho final. Em projetos modernos, o dx foi substituído pelo D8 (introduzido no Android Studio 3.1), que é 2–3 vezes mais rápido e suporta desugar do Java 8.
// Exemplo de bytecode DEX descompilado via dexdump
// Código fonte: return a + b;
@Ldalvik/annotation/Code;
registers: 3
add-int v0, v1, v2
return v0
A limitação do formato DEX de 65.536 métodos (limite de índice de 16 bits) tornou-se um problema sério para aplicativos grandes. A solução veio com o Android 5.0: o suporte a multi-dex permite que um aplicativo contenha vários arquivos DEX. O principal classes.dex contém pontos de entrada, enquanto classes2.dex, classes3.dex adicionais e assim por diante contêm o restante do código. A configuração multi-dex é habilitada no build.gradle com a linha multiDexEnabled true.
A coleta de lixo no Dalvik é implementada como um coletor geracional com marcação e varredura (mark-and-sweep). A memória é dividida em duas áreas principais: Heap (monte) para objetos e Stack (pilha) para primitivos e referências. Quando o Heap enche, o Dalvik suspende todas as threads (STW — Stop-The-World), marca objetos alcançáveis e libera os inalcançáveis.
Antes do Android 2.2, o Dalvik usava um coletor de thread único com durações de pausa de até 100–200 ms. O Android 2.3 Gingerbread introduziu um coletor concorrente que reduziu as pausas típicas para 5–10 ms. E o Android 4.0 Ice Cream Sandwich adicionou um coletor com limpeza incremental — Concurrent Mark and Sweep (CMS).
Um problema típico de aplicativos Dalvik são os vazamentos de memória através de referências estáticas para Activity. Se um campo estático mantém uma referência a Context ou View, o coletor de lixo não pode liberar a Activity mesmo após fechar a tela. Ferramentas como Eclipse MAT e LeakCanary ajudam a detectar tais vazamentos: elas analisam um dump do Heap e mostram cadeias de referências que seguram o objeto.
// Exemplo de vazamento de memória através de referência estática
public class Utils {
private static Context context;
public static void init(Context ctx) {
context = ctx; // Mantém Activity após finish()
}
}
Apesar de seu sucesso, o Dalvik tinha várias desvantagens. A compilação JIT exigia tempo de aquecimento — os primeiros segundos de operação do aplicativo eram mais lentos. Além disso, o JIT consumia energia da CPU durante a compilação, reduzindo a vida útil da bateria. À medida que o desempenho dos dispositivos móveis crescia e o armazenamento embutido aumentava, a necessidade do JIT diminuía.
No Android 4.4 KitKat, o Google apresentou o ART (Android Runtime) como substituição experimental do Dalvik. A partir do Android 5.0 Lollipop, o ART se tornou o único ambiente de execução. A principal diferença é a compilação AOT: em vez de compilar durante a execução, todos os aplicativos são compilados em código de máquina durante a instalação. Isso eliminou os atrasos de aquecimento e melhorou a eficiência energética.
A transição do Dalvik para o ART foi transparente para os desenvolvedores: ambos os ambientes executam o mesmo bytecode DEX. Aplicativos compilados para Dalvik funcionam no ART sem recompilação — o system_server os compila em código nativo durante a instalação. A exceção é o código que usa reflexão para acessar membros internos da VM Dalvik: tal código pode quebrar no ART devido a mudanças na arquitetura interna.
Perguntas frequentes
Dalvik é um programa intermediário que executa aplicativos Android no telefone. Ele pega o código do aplicativo e o converte em comandos compreensíveis pelo processador, fazendo isso diretamente enquanto o usuário trabalha.
O Dalvik usa uma arquitetura baseada em registradores e o formato DEX, enquanto a JVM usa uma arquitetura baseada em pilha e o formato class. O Dalvik é otimizado para dispositivos móveis com memória e poder de processamento limitados, enquanto a JVM é projetada para computadores de mesa e servidores.
O ART oferece maior desempenho através da compilação AOT antecipada — o aplicativo é compilado uma vez durante a instalação, não toda vez que é iniciado. Isso acelera a operação e economiza bateria em comparação com a abordagem JIT do Dalvik.
Sim, o ART é totalmente compatível com o bytecode DEX do Dalvik. Durante a instalação, o ART compila arquivos DEX antigos em código nativo. A exceção são aplicativos que usam reflexão para acessar mecanismos internos do Dalvik.
DEX (Dalvik Executable) é um formato de arquivo executável contendo bytecode compactado de um aplicativo Android. Um único APK pode conter vários arquivos DEX (multi-dex) se o aplicativo tiver mais de 65.536 métodos.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também