JIT: o que é a compilação Just-In-Time e como funciona

Autor: IT Sectr Publicado: 2026-04-16 Tempo de leitura: 9 min

JIT (Just-In-Time) é uma tecnologia de compilação dinâmica que converte bytecode ou representação intermediária de programa em instruções de máquina diretamente durante a execução. No Android, o compilador JIT apareceu pela primeira vez na versão 2.2 Froyo como parte da máquina virtual Dalvik e acelerou a execução de aplicativos em 2–5 vezes. De acordo com Google, 2024, o JIT moderno no ART combina interpretação com compilação perfilada de métodos hot.

Principais conclusões

  • JIT — compilação Just-In-Time: conversão de código em código de máquina diretamente enquanto o programa está em execução.
  • No Dalvik, o JIT compilava métodos hot após exceder o limite de chamadas (~200 vezes).
  • O JIT reduz o tempo de instalação e ocupa menos espaço que a compilação AOT completa.
  • A principal desvantagem é o atraso de aquecimento: nos primeiros segundos o aplicativo funciona mais devagar.
  • No ART moderno, o JIT é usado em modo híbrido com otimização AOT em segundo plano.

O que é compilação JIT?

Just-In-Time (JIT) é um método de compilação no qual o código fonte ou bytecode é convertido em instruções de máquina não antecipadamente (como no AOT), mas no momento da primeira chamada à seção correspondente do programa. O termo “Just-In-Time” significa que a compilação ocorre “na hora certa” — imediatamente antes da execução.

O conceito de JIT existe desde a década de 1960, mas ganhou ampla adoção com o advento da Máquina Virtual Java em 1995. O JIT permite combinar a portabilidade do bytecode (escreva uma vez — execute em qualquer lugar) com desempenho próximo ao código nativo. Na JVM HotSpot, o compilador JIT analisa o código executado e compila apenas as seções mais críticas, economizando tempo e memória.

Como funciona

O compilador JIT recebe bytecode como entrada, interpreta-o e simultaneamente coleta estatísticas. Quando uma seção de código (método, loop) é chamada com frequência suficiente, o JIT decide compilá-la. O código de máquina compilado é armazenado em cache — em chamadas subsequentes, a versão já compilada é usada. Isso fornece aceleração sem ter que compilar o programa inteiro.

java
// Exemplo: um método se torna hot após múltiplas chamadas
public class HotMethod {
    private int compute(int n) {
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += i * i;
        }
        return sum;
    }
}

// Chamar 500 vezes em um loop — JIT compilará compute
for (int t = 0; t < 500; t++) {
    hot.compute(1000);
}

JIT no Android: Dalvik e ART

No Android, a compilação JIT passou por três fases de evolução. A primeira fase — Dalvik sem JIT (Android 1.0–2.1): interpretação pura do bytecode DEX. A segunda fase — Dalvik com JIT (Android 2.2–4.4): a introdução do compilador JIT, que acelerou os aplicativos em 2–5 vezes. A terceira fase — ART com JIT híbrido (Android 7.0+): o retorno do JIT em uma nova capacidade.

O JIT no Dalvik foi implementado como um compilador baseado em traços. Ele analisava não métodos individuais, mas cadeias de instruções (traços) que são executadas sequencialmente com frequência. Isso permitia compilar caminhos de execução completos, incluindo vários métodos. Essa abordagem era eficaz para processadores móveis com pequenos caches de instrução, pois o traço compilado cabia no cache L1.

JIT no ART moderno

A partir do Android 7.0 Nougat, o ART usa JIT baseado em métodos — compila métodos individuais com base em perfis de execução. Este JIT funciona significativamente mais rápido que o Dalvik JIT: o tempo típico de compilação de um método é de 0.5–1 ms contra 3–5 ms no Dalvik. O código compilado é armazenado em uma área de memória separada (cache de código JIT) em vez do heap do aplicativo, o que reduz a fragmentação.

ParâmetroDalvik JITART JIT
TipoBaseado em traçosBaseado em métodos
Velocidade de compilação3–5 ms/método0.5–1 ms/método
Limite de compilação~200 chamadasDinâmico
Cache de códigoNo heap do aplicativoCache de código JIT
PerfilamentoInternoArquivos .prof externos

Detecção de métodos hot e limites de compilação

O mecanismo central do JIT é a detecção de métodos hot. Cada chamada de método incrementa um contador interno. Quando o contador ultrapassa o limite, o método é marcado como “hot” e enviado para compilação. No Dalvik, o limite era fixo (~200 chamadas). No ART, os contadores são configurados dinamicamente dependendo dos recursos disponíveis do dispositivo.

O processo de compilação inclui várias fases. A primeira — análise de bytecode: o JIT examina o fluxo de instruções e constrói um grafo de fluxo de dados. A segunda — otimização: inlining de métodos pequenos, eliminação de código morto, dobramento de constantes. A terceira — geração de código: conversão do grafo otimizado em instruções de máquina para uma arquitetura de CPU específica (ARM, ARM64, x86).

java
// Demonstração de inlining — JIT inlineará o corpo do método
public int inlineExample() {
    return square(5);
}

private int square(int x) {
    return x * x;
} // JIT substituirá a chamada por return 5 * 5;

OSR — Substituição na Pilha (On-Stack Replacement)

Uma técnica especial do JIT — On-Stack Replacement (OSR). Se um método contém um loop longo que não termina por centenas de iterações, o JIT pode compilar o loop “sob demanda” e substituir a versão interpretada pela compilada diretamente durante a execução. O OSR é especialmente eficaz para tarefas computacionais: renderização, processamento de imagens, criptografia.

JIT vs AOT: análise comparativa

JIT e AOT são duas abordagens de compilação com compromissos opostos. O JIT sacrifica a velocidade do primeiro lançamento por um tamanho de distribuição compacto e adaptabilidade. O AOT sacrifica o tempo de instalação e o espaço em disco pelo máximo desempenho desde o primeiro segundo. Nenhuma abordagem é absolutamente melhor — a escolha depende do cenário.

A principal vantagem do JIT é a otimização adaptativa. O JIT pode usar informações de perfil indisponíveis para o AOT: tipos exatos de objetos, frequência real de chamadas, padrões reais de ramificação. Isso permite aplicar otimizações agressivas impossíveis com a compilação estática. Por exemplo, o JIT pode desvirtualizar chamadas de método se apenas um tipo de receptor for encontrado na prática.

CritérioJITAOT
Tempo de instalaçãoInstantâneoDepende do tamanho
Primeiro lançamentoMais lento (aquecimento)Rápido
Espaço em discoMínimo+15–30%
AdaptabilidadeAltaBaixa
Uso de CPUPicos durante compilaçãoEstável

Quando escolher JIT

A compilação JIT é preferível quando a implantação rápida e a economia de espaço em disco são importantes. No contexto do desenvolvimento mobile, o JIT é ideal para aplicativos que são atualizados com frequência (testes A/B, hotfixes). O JIT também é conveniente durante o desenvolvimento, quando o código é reconstruído dezenas de vezes ao dia — cada segundo economizado na compilação acelera o ciclo de feedback.

Vantagens da compilação JIT

JIT fornece aos desenvolvedores uma série de vantagens práticas. A primeira — tamanho pequeno do APK. Com a abordagem JIT, apenas o bytecode (DEX) é empacotado no APK, que ocupa 20–30% menos espaço que o código nativo compilado. Para usuários com armazenamento interno limitado, esta é uma vantagem significativa.

A segunda vantagem é a adaptação ao dispositivo. O JIT compila código levando em conta a arquitetura real da CPU, a quantidade de RAM e a carga atual. Por exemplo, em um dispositivo com 2 GB de RAM, o JIT pode compilar de forma menos agressiva para economizar memória, enquanto em um flagship com 12 GB, pode aplicar todas as otimizações possíveis. A compilação AOT, por outro lado, fixa a decisão no momento da instalação.

Independência de plataforma

O bytecode permanece independente de plataforma, o que simplifica a distribuição de aplicativos. Um único APK funciona em dispositivos ARM, ARM64 e x86, e o JIT gera código nativo para cada arquitetura. A abordagem AOT exigiria incluir múltiplas variantes de código nativo no APK (aumentando o tamanho) ou compilar uma versão separada para cada arquitetura.

Desvantagens e limitações do JIT

A principal desvantagem do JIT é o atraso de aquecimento. O usuário experimenta lentidão nos primeiros segundos do aplicativo enquanto o JIT compila os métodos hot. Em jogos, isso se manifesta como gaguejo nos níveis iniciais. Em aplicativos com animações — transições bruscas entre telas.

A segunda desvantagem — consumo de energia. O processo de compilação carrega intensamente a CPU, aumentando o consumo de energia em 10–20% durante o período de aquecimento. Em dispositivos com bateria, isso reduz a autonomia. É especialmente perceptível em cenários com reinicializações frequentes de aplicativos (multitarefa com memória limitada, onde o sistema descarrega e recarrega processos).

Fragmentação de cache

Outro problema — a fragmentação do cache JIT. O código compilado é armazenado em uma área contínua de memória. Quando novas classes são carregadas e métodos adicionais são compilados, o cache se fragmenta, aumentando a sobrecarga de gerenciamento de memória. No Dalvik, esse problema era resolvido com a limpeza periódica do cache; no ART, o cache JIT é alocado separadamente do heap e usa sua própria estratégia de desfragmentação.

Modo híbrido: o melhor dos dois mundos

A abordagem moderna no ART — a compilação híbrida, combinando os pontos fortes do JIT e do AOT. Durante a instalação do aplicativo, nenhuma compilação é realizada — apenas verificação de bytecode (verify). Isso garante instalação rápida e uso mínimo de espaço. Os primeiros lançamentos ocorrem em modo de interpretação com compilação JIT de métodos hot — o usuário obtém desempenho aceitável sem longos tempos de espera.

Simultaneamente, um perfilador em segundo plano coleta dados sobre o uso real. Após 2–3 lançamentos completos do aplicativo, o perfil atinge completude suficiente, e o sistema executa o dex2oat para compilar os métodos hot em código nativo. Esta operação é realizada em segundo plano quando o dispositivo não está carregado (carregando, tela desligada). Após a conclusão do AOT em segundo plano, o aplicativo atinge desempenho comparável à compilação AOT completa.

bash
# Início forçado de compilação em segundo plano
adb shell cmd package compile -m speed-profile -f com.example.app

# Ver status da compilação
adb shell cmd package dump-profiles com.example.app

Resultados da abordagem híbrida

De acordo com o Google I/O 2017, a compilação híbrida reduziu o tempo de instalação de aplicativos em 30–50% em comparação com o AOT puro. O espaço ocupado na partição do sistema diminuiu 20–30%. Ao mesmo tempo, o desempenho após a compilação em segundo plano corresponde ao nível do AOT completo. O único cenário onde o híbrido fica aquém do AOT é o primeiro lançamento imediatamente após a instalação: o aplicativo funciona em modo JIT e pode ser 10–15% mais lento.

Perguntas frequentes

O que é compilação JIT em termos simples?

JIT é uma forma de acelerar um programa onde o código é traduzido para linguagem de máquina não antecipadamente, mas em partes durante a execução. As seções mais frequentes são compiladas e armazenadas em cache, enquanto as raras permanecem em sua forma original.

Como o JIT difere do AOT?

JIT compila código durante a execução, economizando espaço e acelerando a instalação. O AOT compila todo o código antecipadamente — o aplicativo inicia mais rápido, mas requer mais espaço em disco e tempo de instalação.

Por que o JIT foi removido do Android?

O JIT não foi removido — ele evoluiu. No Android 5.0, o Dalvik com JIT foi substituído pelo ART com AOT puro. No Android 7.0, o JIT retornou ao ART como parte de um sistema híbrido onde trabalha junto com a compilação AOT em segundo plano para desempenho ideal.

Como o JIT afeta o consumo de energia?

JIT aumenta o consumo de energia em 10–20% durante o período de aquecimento devido à carga da CPU. Após a conclusão da compilação dos métodos hot, o consumo de energia retorna aos níveis normais. O modo híbrido do ART minimiza esses picos através da compilação em segundo plano.

O aquecimento do JIT é visível para o usuário?

Sim, em cenários com cálculos intensivos. O usuário pode notar lentidão nos primeiros segundos de operação do aplicativo ou no início de um jogo. Nas versões modernas do Android (8.0+), o modo híbrido minimiza esse efeito graças à compilação perfilada.

Resumo

  • JIT (Just-In-Time) é uma compilação dinâmica que converte bytecode em instruções de máquina durante a execução.
  • No Android, o JIT evoluiu: baseado em traços no Dalvik → AOT completo → JIT+AOT híbrido no ART moderno.
  • Os métodos hot são detectados através de contadores de chamadas e compilados ao ultrapassar o limite (~200 chamadas).
  • OSR (On-Stack Replacement) permite compilar loops longos sob demanda sem interromper a execução.
  • Principais vantagens do JIT: tamanho pequeno do APK, instalação rápida e adaptação ao dispositivo.
  • Principais desvantagens: atraso de aquecimento, consumo máximo de energia e fragmentação de cache.
  • O modo híbrido do ART (Android 7.0+) reduz o tempo de instalação em 30–50% mantendo alto desempenho.

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.

Discutir o projeto

Leia também