DEX: o que é, estrutura e princípio de funcionamento do bytecode

Autor: IT Sectr Publicado: 2026-04-15 Tempo de leitura: 8 min

DEX (Dalvik Executable) é um formato de bytecode no qual o código-fonte de aplicações Android em Java e Kotlin é compilado. Os arquivos DEX são executados pela máquina virtual Dalvik (até Android 4.4) ou pelo Android Runtime (ART, a partir do Android 5.0). De acordo com Android Open Source Project, 2026, o formato DEX fornece em média 30% de representação de código mais compacta em comparação com o bytecode Java padrão da JVM.

Pontos principais

  • DEX é um formato de bytecode para Android, executado no Dalvik ou ART.
  • Compacidade — DEX ocupa 30% menos espaço que o bytecode Java padrão.
  • Multidex — um mecanismo para contornar o limite de 65536 métodos em um único arquivo DEX.
  • ART — Android Runtime, que substituiu o Dalvik, compila DEX em código nativo durante a instalação.
  • D8 — um compilador moderno de Java/Kotlin para DEX, substituindo o DX desde 2018.

O que é DEX e para que serve

DEX (Dalvik Executable) é um formato de bytecode projetado especificamente para dispositivos móveis Android. Diferente do bytecode Java padrão (arquivos .class), o DEX é otimizado para recursos limitados: menos memória, tamanho menor e carregamento de classes mais rápido.

De Java para DEX

O código-fonte em Java ou Kotlin é compilado por javac/kotlinc em arquivos .class padrão (bytecode Java). Em seguida, a ferramenta d8 (ou anteriormente dx) converte .class em um ou mais arquivos DEX. Esta conversão não é um simples reempacotamento — o d8 realiza otimizações: mescla pools de constantes, reescreve instruções em arquitetura de registradores e remove dados duplicados.

Características arquiteturais

O DEX usa uma arquitetura baseada em registradores (ao contrário da JVM baseada em pilha). Cada método tem um número fixo de registradores (até 65536). As instruções DEX são mais curtas — em média 2 bytes contra 1–4 bytes na JVM. Isso produz código mais compacto: uma aplicação típica reduz de 10–15 MB de .class para 4–6 MB de .dex.

Estrutura do arquivo DEX: seções e cabeçalho

Um arquivo DEX tem uma estrutura binária estritamente definida. Cada arquivo começa com um cabeçalho e contém várias seções que se referenciam mutuamente através de offsets.

SeçãoPropósito
headerCabeçalho: magic, checksum, assinatura, tamanhos e offsets das seções
string_idsTabela de strings: nomes de classes, métodos, campos
type_idsTipos: referências a identificadores de string de tipos
proto_idsProtótipos de métodos: tipo de retorno e parâmetros
field_idsCampos de classes: classe, tipo, nome
method_idsMétodos: classe, protótipo, nome
class_defsDefinições de classes: flags, superclasse, interfaces, offsets de dados
dataDados reais: código dos métodos, anotações, informações de debug

Cabeçalho DEX

O número mágico do DEX é `dex\n035\0` (versão 035). Outras versões: 036, 037, 038 (para Android 8.0+). O cabeçalho tem 0x70 bytes e contém um checksum SHA-1 e os offsets de todas as seções. A validação do cabeçalho é o primeiro passo ao carregar um DEX na máquina virtual.

Pools de constantes

string_ids, type_ids, proto_ids, field_ids, method_ids — são tabelas indexadas. Em vez de armazenar nomes completos no código do método, é usado um índice de 4 bytes. Esta é uma otimização chave: se uma classe é mencionada 100 vezes, seu nome é armazenado uma vez em string_ids. dex2oat otimiza ainda mais essas tabelas durante a compilação ART.

Processo de compilação de Java e Kotlin para DEX

O processo de conversão do código-fonte em DEX consiste em várias etapas. A cadeia de ferramentas moderna usa o compilador D8, que substituiu o DX em 2018 com o Android Gradle Plugin 3.2.

Etapa 1: Compilação para .class

javac (para Java) ou kotlinc (para Kotlin) compila o código-fonte em arquivos .class. Cada classe é um arquivo .class separado em bytecode Java. Nesta etapa, são realizadas verificação de tipos, geração de métodos bridge e inlining de constantes.

Etapa 2: Compilação D8

D8 recebe todos os arquivos .class e os transforma em bytecode DEX. O D8 realiza várias otimizações: remove argumentos de métodos não utilizados, mescla pools de constantes de diferentes arquivos .class em um pool global DEX e converte instruções de pilha JVM em instruções de registrador Dalvik.

kotlin
// Código-fonte Kotlin
data class User(
    val name: String,
    val email: String
)

fun greet(user: User): String {
    return "Hello, ${user.name}!"
}

Após a compilação D8, este código se transforma em instruções DEX compactas: const-string para carregar strings, iget-object para acessar o campo de um objeto, invoke-virtual para chamar StringBuilder.append.

D8 vs DX

D8 é 2–3 vezes mais rápido que o DX, gera DEX mais compacto (5–10% menor) e otimiza melhor construções específicas do Kotlin (funções inline, lambdas). O DX foi declarado obsoleto em 2018 e removido do Android Gradle Plugin 8.0.

Dalvik vs ART: como a execução do DEX mudou

A execução do código DEX no Android passou por duas fases: a máquina virtual Dalvik original (Android 2.2–4.4) e o Android Runtime ART (Android 5.0+). A diferença na abordagem de compilação é fundamental.

Dalvik VM: compilação JIT

Dalvik usava compilação Just-In-Time (JIT): o bytecode DEX era interpretado e os métodos chamados com frequência eram compilados para código nativo em tempo real. Vantagem — instalação rápida. Desvantagem — inicialização mais lenta e consumo constante de CPU para JIT.

ART: compilação AOT

ART (Android Runtime) compila DEX em código nativo durante a instalação do aplicativo via dex2oat. Esta é uma abordagem Ahead-Of-Time (AOT): a instalação é mais lenta, mas a inicialização é mais rápida e o consumo de energia é menor. Desde o Android 7.0, o ART usa uma abordagem híbrida — AOT + JIT + Profile Guided Optimization.

dex2oat: conversão durante a instalação

A ferramenta dex2oat é executada ao instalar ou atualizar um aplicativo. Ela compila DEX em um arquivo ELF com código nativo para a arquitetura do dispositivo. O resultado — arquivos .oat e .art no diretório /data/dalvik-cache/. O Google melhora continuamente o dex2oat: no Android 14, foram adicionadas otimizações para dispositivos dobráveis.

Multidex: superando o limite de 64K métodos

O limite de 65536 métodos por arquivo DEX é um legado da arquitetura Dalvik. O campo method_ids no cabeçalho DEX ocupa 4 bytes, dando um máximo de 2^16 = 65536 referências únicas. Aplicativos modernos com Google Play Services, Firebase e outros SDKs excedem facilmente esse limite.

Mecanismo Multidex

Multidex é um mecanismo para dividir o código em vários arquivos DEX. O classes.dex principal contém os pontos de entrada (classe Application, Activity principal), os demais são classes2.dex, classes3.dex e assim por diante. Na inicialização, as classes dos DEX adicionais são carregadas via DexClassLoader.

kotlin
// build.gradle.kts — habilitação do multidex
android {
    defaultConfig {
        multiDexEnabled = true
    }
}

// Classe Application com suporte a multidex
class MyApp : Application() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

Problemas do Multidex

O carregamento de DEX adicionais durante a inicialização do aplicativo pode causar ANR (Application Not Responding) em dispositivos com Android anterior ao 5.0. Recomendação — usar multidex apenas quando necessário e minimizar as dependências para não exceder o limite.

Otimização de DEX: ProGuard, R8 e ofuscação

A otimização de DEX é uma etapa padrão na construção de um aplicativo Android de versão. As ferramentas R8 e ProGuard reduzem o tamanho do DEX, ofuscam o código e removem classes não utilizadas.

R8 vs ProGuard

R8 é o sucessor do ProGuard, integrado ao Android Gradle Plugin desde 2019. O R8 realiza minificação, ofuscação e otimização em uma única passada, enquanto o ProGuard exigia duas etapas: ProGuard → D8. ProGuard ainda é suportado, mas o Google recomenda o R8 para novos projetos.

O R8 remove classes, métodos e campos não utilizados, renomeia-os com nomes curtos (a, b, c), incorpora funções inline e elimina código morto. O resultado — o DEX é reduzido em 20–40% sem perda de funcionalidade.

Regras do R8

A configuração do R8 é especificada no arquivo proguard-rules.pro. O desenvolvedor pode indicar quais classes não podem ser renomeadas (por exemplo, para reflexão ou serialização Gson). Firebase e outros SDKs fornecem suas próprias regras em suas dependências.

Descompilação de DEX: ferramentas e proteção

DEX pode ser descompilado de volta para código Java. Esta é uma questão chave de segurança para aplicativos Android: sem ofuscação, o código é restaurado a um nível próximo do original.

Ferramentas de descompilação

JADX é o descompilador de DEX para Java mais popular. Ele restaura nomes de classes, métodos, campos e grande parte da lógica. apktool descompila DEX em código smali (montador Dalvik) — uma representação de baixo nível próxima às instruções originais. Bytecode Viewer combina vários descompiladores em uma interface.

Métodos de proteção

A ofuscação com R8/ProGuard é a primeira linha de defesa: nomes de classes e métodos tornam-se ilegíveis. DexGuard é uma ferramenta comercial com métodos adicionais: criptografia de strings, verificação de integridade, anti-adulteração. A ofuscação de fluxo de controle (O-LLVM) altera a estrutura do código mantendo sua funcionalidade, tornando a análise muito mais difícil.

Perguntas frequentes

Como o DEX difere do bytecode Java?

DEX usa uma arquitetura baseada em registradores em vez da JVM baseada em pilha, tem um formato mais compacto (30% menor), mescla todos os .class em um único arquivo com um pool de constantes unificado e usa índices de 16 bits em vez de 8 bits.

O que é smali?

Smali é um montador de bytecode DEX. Cada instrução DEX tem uma representação textual no formato smali. A ferramenta baksmali converte DEX em smali (desmontagem), e smali monta smali de volta em DEX.

Como verificar o número de métodos no DEX?

A tarefa Gradle countMethods ou o plugin dex-method-counts mostram o número de métodos em cada arquivo DEX. O comando adb shell com dumpsys também exibe estatísticas dos DEX carregados para aplicativos instalados.

O número de arquivos DEX afeta o desempenho?

Sim, em dispositivos com Android anterior ao 8.0, múltiplos arquivos DEX retardam a inicialização do aplicativo porque cada arquivo adicional é carregado separadamente. No ART com Android 8.0+, a diferença é mínima graças à compilação dex2oat em um único arquivo .oat.

É possível executar DEX sem Android?

Sim, existem projetos como dexplorer e implementações JVM compatíveis com Android que podem executar bytecode DEX fora do Android. No entanto, a maioria dos arquivos DEX usa a API Android, tornando-os inadequados para execução em uma JVM padrão.

Resumo

  • DEX é um formato de bytecode Android com arquitetura baseada em registradores e representação compacta de código.
  • Estrutura inclui cabeçalho, tabelas de identificadores e seção de dados com instruções.
  • Compilação para DEX é feita via D8: .class → DEX com otimizações e mesclagem de pools de constantes.
  • ART compila DEX em código nativo durante a instalação (AOT), acelerando a inicialização do aplicativo.
  • Multidex resolve o limite de 65536 métodos dividindo em vários arquivos DEX.
  • Otimização — R8 reduz DEX em 20–40%, ofusca nomes e remove código morto.
  • Proteção — ofuscação com R8/ProGuard, DexGuard e O-LLVM previne a descompilação de DEX.

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