DEX: wat is het, structuur en werkingsprincipe van bytecode

Auteur: IT Sectr Gepubliceerd: 2026-04-15 Leestijd: 8 min

DEX (Dalvik Executable) is het bytecodeformaat waarin de broncode van Android-applicaties in Java en Kotlin wordt gecompileerd. DEX-bestanden worden uitgevoerd door de Dalvik virtuele machine (tot Android 4.4) of Android Runtime (ART, vanaf Android 5.0). Volgens gegevens van Android Open Source Project, 2026 biedt het DEX-formaat gemiddeld 30% compactere codeweergave in vergelijking met standaard JVM-bytecode.

Belangrijkste punten

  • DEX — bytecodeformaat voor Android, uitvoerbaar op Dalvik of ART.
  • Compactheid — DEX neemt 30% minder ruimte in dan standaard Java-bytecode.
  • Multidex — mechanisme om de limiet van 65536 methoden in één DEX-bestand te omzeilen.
  • ART — Android Runtime, dat Dalvik verving, compileert DEX bij installatie naar native code.
  • D8 — moderne compiler Java/Kotlin naar DEX, die DX sinds 2018 heeft vervangen.

Wat is DEX en waarvoor dient het

DEX (Dalvik Executable) is een bytecodeformaat dat speciaal is ontworpen voor Android-mobiele apparaten. In tegenstelling tot standaard Java-bytecode (.class-bestanden) is DEX geoptimaliseerd voor beperkte bronnen: minder geheugen, kleinere omvang en snellere klassen laden.

Van Java naar DEX

Broncode in Java of Kotlin wordt door javac/kotlinc gecompileerd naar standaard .class-bestanden (Java-bytecode). Vervolgens converteert de tool d8 (of eerder dx) de .class-bestanden naar een of meerdere DEX-bestanden. Deze conversie is niet simpelweg herverpakken — d8 voert optimalisaties uit: het voegt constante pools samen, herschrijft instructies naar registerarchitectuur en verwijdert dubbele gegevens.

Architectuurkenmerken

DEX gebruikt een registerarchitectuur (in tegenstelling tot de stackgebaseerde JVM). Elke methode heeft een vast aantal registers (tot 65536). DEX-instructies zijn korter — gemiddeld 2 bytes tegenover 1–4 bytes in JVM. Dit levert compactere code op: een typische applicatie krimpt van 10–15 MB .class naar 4–6 MB .dex.

Structuur van een DEX-bestand: secties en header

Een DEX-bestand heeft een strikt gedefinieerde binaire structuur. Elk bestand begint met een header en bevat verschillende secties die naar elkaar verwijzen via offsets.

SectieDoel
headerHeader: magic, controlesom, handtekening, groottes en offsets van secties
string_idsTabel met strings: namen van klassen, methoden, velden
type_idsTypes: verwijzingen naar stringidentificaties van types
proto_idsMethodeprototypes: retourtype en parameters
field_idsKlassenvelden: klasse, type, naam
method_idsMethoden: klasse, prototype, naam
class_defsKlassedefinities: vlaggen, superclass, interfaces, gegevensoffsets
dataWerkelijke gegevens: methodencode, annotaties, debug-info

DEX-header

Het magische getal van DEX — `dex\n035\0` (versie 035). Andere versies: 036, 037, 038 (voor Android 8.0+). De header van 0x70 bytes bevat een SHA-1-controlesom en offsets van alle secties. Validatie van de header is de eerste stap bij het laden van DEX door de virtuele machine.

Constante pools

string_ids, type_ids, proto_ids, field_ids, method_ids — zijn geïndexeerde tabellen. In plaats van volledige namen in de methodencode op te slaan, wordt een 4-byte index gebruikt. Dit is de belangrijkste optimalisatie: als een klasse 100 keer wordt genoemd, wordt de naam één keer opgeslagen in string_ids. dex2oat optimaliseert deze tabellen verder tijdens ART-compilatie.

Compilatieproces van Java en Kotlin naar DEX

Het proces van het omzetten van broncode naar DEX bestaat uit verschillende fasen. De moderne keten gebruikt de D8-compiler, die in 2018 met Android Gradle Plugin 3.2 DX verving.

Fase 1: Compilatie naar .class

javac (voor Java) of kotlinc (voor Kotlin) compileren broncode naar .class-bestanden. Elke klasse is een apart .class-bestand in Java-bytecode. In deze fase worden typecontrole, generatie van bridge-methoden en inlining van constanten uitgevoerd.

Fase 2: D8-compilatie

D8 neemt alle .class-bestanden en zet ze om in DEX-bytecode. D8 voert verschillende optimalisaties uit: verwijdert ongebruikte methode-argumenten, voegt constante pools uit verschillende .class-bestanden samen in één globale DEX-pool, converteert JVM-stackinstructies naar Dalvik-registerinstructies.

kotlin
// Kotlin-broncode
data class User(
    val name: String,
    val email: String
)

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

Na D8-compilatie wordt deze code omgezet in compacte DEX-instructies: const-string voor het laden van een string, iget-object voor toegang tot een objectveld, invoke-virtual voor het aanroepen van StringBuilder.append.

D8 vs DX

D8 werkt 2–3 keer sneller dan DX, genereert compactere DEX (5–10%) en optimaliseert Kotlin-specifieke constructies (inline functies, lambda) beter. DX is sinds 2018 als deprecated gemarkeerd en verwijderd uit Android Gradle Plugin 8.0.

Dalvik vs ART: hoe de uitvoering van DEX veranderde

De uitvoering van DEX-code in Android heeft twee fasen doorlopen: de originele Dalvik virtuele machine (Android 2.2–4.4) en Android Runtime ART (Android 5.0+). Het verschil in benadering van compilatie is fundamenteel.

Dalvik VM: JIT-compilatie

Dalvik gebruikte Just-In-Time (JIT) compilatie: DEX-bytecode werd geïnterpreteerd en veelgebruikte methoden werden ter plekke naar native code gecompileerd. Voordeel — snelle installatie. Nadeel — tragere opstart en constante CPU-belasting voor JIT.

ART: AOT-compilatie

ART (Android Runtime) compileert DEX bij installatie van de app via dex2oat naar native code. Dit is een Ahead-Of-Time (AOT) benadering: installatie duurt langer, maar opstarten is sneller en energieverbruik lager. Sinds Android 7.0 gebruikt ART een hybride benadering — AOT + JIT + Profile Guided Optimization.

dex2oat: conversie bij installatie

De tool dex2oat wordt uitgevoerd bij installatie of update van een app. Het compileert DEX naar een ELF-bestand met native code voor de apparaatarchitectuur. Resultaat — .oat- en .art-bestanden in de map /data/dalvik-cache/. Google verbetert dex2oat continu: op Android 14 is optimalisatie voor opvouwbare apparaten toegevoegd.

Multidex: de 64K-methodelimiet overwinnen

De beperking van 65536 methoden per DEX-bestand is een erfenis van de Dalvik-architectuur. Het veld method_ids in de DEX-header beslaat 4 bytes, wat maximaal 2^16 = 65536 unieke verwijzingen geeft. Moderne apps met Google Play Services, Firebase en andere SDK's overschrijden deze limiet gemakkelijk.

Multidex-mechanisme

Multidex is een mechanisme om code te verdelen over meerdere DEX-bestanden. Het hoofdbestand classes.dex bevat de ingangspunten (Application-klasse, hoofd-Activity), de rest — classes2.dex, classes3.dex enzovoort. Bij het opstarten worden klassen uit extra DEX-bestanden geladen via DexClassLoader.

kotlin
// build.gradle.kts — multidex inschakelen
android {
    defaultConfig {
        multiDexEnabled = true
    }
}

// Application-klasse met multidex-ondersteuning
class MyApp : Application() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

Problemen met Multidex

Het laden van extra DEX-bestanden tijdens de opstartfase kan ANR (Application Not Responding) veroorzaken op apparaten met Android tot 5.0. Aanbeveling — gebruik multidex alleen wanneer nodig en minimaliseer afhankelijkheden om de limiet niet te overschrijden.

DEX-optimalisatie: ProGuard, R8 en obfuscatie

DEX-optimalisatie is een standaard fase in het bouwen van een releaseversie van een Android-app. De tools R8 en ProGuard verkleinen de DEX, obfusceren code en verwijderen ongebruikte klassen.

R8 vs ProGuard

R8 — de opvolger van ProGuard, geïntegreerd in Android Gradle Plugin sinds 2019. R8 voert minificatie, obfuscatie en optimalisatie uit in één pass, terwijl ProGuard twee fasen nodig had: ProGuard → D8. ProGuard wordt nog steeds ondersteund, maar Google beveelt R8 aan voor nieuwe projecten.

R8 verwijdert ongebruikte klassen, methoden en velden, hernoemt ze naar korte namen (a, b, c), inlineert functies en verwijdert dode code. Resultaat — DEX wordt 20–40% kleiner zonder functionaliteitsverlies.

R8-regels

De configuratie van R8 wordt ingesteld in het bestand proguard-rules.pro. De ontwikkelaar kan aangeven welke klassen niet hernoemd mogen worden (bijvoorbeeld voor reflectie of Gson-serialisatie). Firebase en andere SDK's leveren eigen regels in hun afhankelijkheden.

DEX-decompilatie: tools en bescherming

DEX kan terug worden gedecompileerd naar Java-code. Dit is een belangrijk beveiligingsvraagstuk voor Android-apps: zonder obfuscatie wordt code hersteld tot een niveau dat dicht bij het origineel ligt.

Decompilatie-tools

JADX — de meest populaire decompiler van DEX naar Java. Het herstelt klassenamen, methoden, velden en het grootste deel van de logica. apktool decompileert DEX naar smali-code (Dalvik-assembler) — een laag-niveau weergave dicht bij de oorspronkelijke instructies. Bytecode Viewer combineert meerdere decompilers in één interface.

Beschermingsmethoden

Obfuscatie met R8/ProGuard — de eerste verdedigingslinie: klassen- en methodenamen worden onleesbaar. DexGuard — commerciële tool met extra methoden: stringversleuteling, integriteitscontrole, anti-tamper. Obfuscatie op Control Flow-niveau (O-LLVM) wijzigt de codestructuur, behoudt functionaliteit, maar maakt analyse veel moeilijker.

Veelgestelde vragen

Waarin verschilt DEX van Java-bytecode?

DEX gebruikt registerarchitectuur in plaats van de stackgebaseerde JVM, heeft een compacter formaat (30% kleiner), voegt alle .class-bestanden samen in één bestand met een uniforme constante pool en gebruikt 16-bits indices in plaats van 8-bits.

Wat is smali?

Smali — is de assembler van DEX-bytecode. Elke DEX-instructie heeft een tekstuele weergave in smali-formaat. De tool baksmali converteert DEX naar smali (disassemblage), en smali assembleert smali terug naar DEX.

Hoe controleer je het aantal methoden in DEX?

Gradle task countMethods of de plugin dex-method-counts tonen het aantal methoden in elk DEX-bestand. Het commando adb shell met dumpsys geeft ook statistieken van geladen DEX-bestanden voor geïnstalleerde apps.

Beïnvloedt het aantal DEX-bestanden de prestaties?

Ja, op apparaten met Android tot 8.0 vertraagt meerdere DEX het opstarten van de app, omdat elk extra bestand afzonderlijk wordt geladen. Op ART met Android 8.0+ is het verschil minimaal dankzij compilatie door dex2oat naar één .oat-bestand.

Kan DEX zonder Android worden uitgevoerd?

Ja, er bestaan projecten zoals dexplorer en Android-compatibele JVM-implementaties die DEX-bytecode buiten Android kunnen uitvoeren. De meeste DEX-bestanden gebruiken echter de Android API, waardoor ze ongeschikt zijn voor uitvoering op een gewone JVM.

Samenvatting

  • DEX — Android-bytecodeformaat met registerarchitectuur en compacte codeweergave.
  • Structuur omvat header, identificatietabellen en een datasectie met instructies.
  • Compilatie naar DEX gebeurt via D8: .class → DEX met optimalisaties en samenvoeging van constante pools.
  • ART compileert DEX bij installatie naar native code (AOT), waardoor de app sneller opstart.
  • Multidex — oplossing voor de limiet van 65536 methoden door verdeling over meerdere DEX-bestanden.
  • Optimalisatie — R8 verkleint DEX met 20–40%, obfusceert namen en verwijdert dode code.
  • Bescherming — obfuscatie met R8/ProGuard, DexGuard en O-LLVM voorkomen DEX-decompilatie.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook