DEX (Dalvik Executable) är det bytekodsformat som Android-applikationers källkod i Java och Kotlin kompileras till. DEX-filer exekveras av Dalviks virtuella maskin (till Android 4.4) eller Android Runtime (ART, från Android 5.0). Enligt data från Android Open Source Project, 2026 ger DEX-formatet i genomsnitt 30% mer kompakt kodrepresentation jämfört med standard JVM-bytekod.
Huvudpunkter
DEX (Dalvik Executable) är ett bytekodsformat speciellt utformat för mobila Android-enheter. Till skillnad från standard Java-bytekod (.class-filer) är DEX optimerat för begränsade resurser: mindre minne, mindre storlek och snabbare klassladdning.
Källkod i Java eller Kotlin kompileras av javac/kotlinc till standard .class-filer (Java-bytekod). Därefter konverterar verktyget d8 (eller tidigare dx) .class-filerna till en eller flera DEX-filer. Denna konvertering är inte enkel omförpackning — d8 utför optimeringar: slår samman konstanta pooler, skriver om instruktioner till registerarkitektur och tar bort dubblettdata.
DEX använder register-arkitektur (till skillnad från JVM:s stackbaserade arkitektur). Varje metod har ett fast antal register (upp till 65536). DEX-instruktioner är kortare — i genomsnitt 2 byte jämfört med 1–4 byte i JVM. Detta ger mer kompakt kod: en typisk applikation minskar från 10–15 MB .class till 4–6 MB .dex.
En DEX-fil har en strikt definierad binär struktur. Varje fil börjar med en rubrik och innehåller flera sektioner som refererar till varandra via offsetar.
| Sektion | Syfte |
|---|---|
| header | Rubrik: magic, kontrollsumma, signatur, storlekar och offsetar för sektioner |
| string_ids | Strängtabell: namn på klasser, metoder, fält |
| type_ids | Typer: referenser till strängidentifierare för typer |
| proto_ids | Metodprototyper: returtyp och parametrar |
| field_ids | Klassfält: klass, typ, namn |
| method_ids | Metoder: klass, prototyp, namn |
| class_defs | Klassdefinitioner: flaggor, superclass, gränssnitt, dataoffsetar |
| data | Faktisk data: metodkod, annoteringar, debug-information |
Det magiska talet för DEX — `dex\n035\0` (version 035). Andra versioner: 036, 037, 038 (för Android 8.0+). Rubriken på 0x70 byte innehåller en SHA-1-kontrollsumma och offsetar för alla sektioner. Validering av rubriken — första steget vid laddning av DEX av den virtuella maskinen.
string_ids, type_ids, proto_ids, field_ids, method_ids — är indexerade tabeller. Istället för att lagra fullständiga namn i metodkoden används ett 4-byte index. Detta är den viktigaste optimeringen: om en klass nämns 100 gånger lagras dess namn en gång i string_ids. dex2oat vid ART-kompilering optimerar ytterligare dessa tabeller.
Processen att omvandla källkod till DEX består av flera steg. Den moderna kedjan använder kompilatorn D8, som ersatte DX 2018 med Android Gradle Plugin 3.2.
javac (för Java) eller kotlinc (för Kotlin) kompilerar källkod till .class-filer. Varje klass — en separat .class-fil i Java-bytekod. I detta steg utförs typkontroll, generering av bridge-metoder och inbäddning av konstanter.
D8 tar emot alla .class-filer och omvandlar dem till DEX-bytekod. D8 utför flera optimeringar: tar bort oanvända metodargument, slår samman konstanta pooler från olika .class till en global DEX-pool, konverterar JVM-stackinstruktioner till Dalvik-registerinstruktioner.
// Kotlin-källkod
data class User(
val name: String,
val email: String
)
fun greet(user: User): String {
return "Hello, ${user.name}!"
}
Efter D8-kompilering omvandlas denna kod till kompakta DEX-instruktioner: const-string för att ladda en sträng, iget-object för att komma åt ett objektfält, invoke-virtual för att anropa StringBuilder.append.
D8 arbetar 2–3 gånger snabbare än DX, genererar mer kompakt DEX (5–10%) och optimerar bättre Kotlin-specifika konstruktioner (inline-funktioner, lambda). DX har markerats som deprecated sedan 2018 och tagits bort från Android Gradle Plugin 8.0.
Exekveringen av DEX-kod i Android har genomgått två faser: den ursprungliga Dalviks virtuella maskin (Android 2.2–4.4) och Android Runtime ART (Android 5.0+). Skillnaden i kompileringsmetod är grundläggande.
Dalvik använde Just-In-Time (JIT)-kompilering: DEX-bytekod tolkades och ofta anropade metoder kompilerades till native-kod i farten. Fördel — snabb installation. Nackdel — långsammare start och konstant CPU-belastning för JIT.
ART (Android Runtime) kompilerar DEX till native-kod vid installation av applikationen via dex2oat. Detta är ett Ahead-Of-Time (AOT)-angreppssätt: installation tar längre tid, men start är snabbare och energiförbrukningen lägre. Från Android 7.0 använder ART ett hybridangreppssätt — AOT + JIT + Profile Guided Optimization.
Verktyget dex2oat körs vid installation eller uppdatering av applikationen. Det kompilerar DEX till en ELF-fil med native-kod för enhetens arkitektur. Resultat — .oat- och .art-filer i katalogen /data/dalvik-cache/. Google förbättrar ständigt dex2oat: i Android 14 lades optimering för hopfällbara enheter till.
Begränsningen på 65536 metoder per DEX-fil — ett arv från Dalvik-arkitekturen. Fältet method_ids i DEX-rubriken upptar 4 byte, vilket ger maximalt 2^16 = 65536 unika referenser. Moderna applikationer med Google Play Services, Firebase och andra SDK:er överskrider lätt denna gräns.
Multidex är en mekanism för att dela upp kod i flera DEX-filer. Huvudfilen classes.dex innehåller ingångspunkter (Application-klassen, huvud-Activity), resten — classes2.dex, classes3.dex och så vidare. Vid start laddas klasser från ytterligare DEX via DexClassLoader.
// build.gradle.kts — aktivera multidex
android {
defaultConfig {
multiDexEnabled = true
}
}
// Application-klass med multidex-stöd
class MyApp : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
}
Laddning av ytterligare DEX i startfasen av applikationen kan orsaka ANR (Application Not Responding) på enheter med Android upp till 5.0. Rekommendation — använd multidex endast vid behov och minimera beroenden för att inte överskrida gränsen.
Optimering av DEX — ett standardsteg vid byggande av en release-version av en Android-applikation. Verktygen R8 och ProGuard minskar DEX-storleken, obfuskerar kod och tar bort oanvända klasser.
R8 — efterträdaren till ProGuard, inbyggd i Android Gradle Plugin sedan 2019. R8 utför minifiering, obfuskering och optimering i en genomgång, medan ProGuard krävde två steg: ProGuard → D8. ProGuard stöds fortfarande, men Google rekommenderar R8 för nya projekt.
R8 tar bort oanvända klasser, metoder och fält, döper om dem till korta namn (a, b, c), bäddar in inline-funktioner och kastar död kod. Resultat — DEX minskar med 20–40% utan funktionalitetsförlust.
Konfigurationen av R8 anges i filen proguard-rules.pro. Utvecklaren kan specificera vilka klasser som inte får döpas om (till exempel för reflektion eller Gson-serialisering). Firebase och andra SDK:er levererar egna regler i sina beroenden.
DEX kan dekompileras tillbaka till Java-kod. Detta är en viktig säkerhetsfråga för Android-applikationer: utan obfuskering återställs kod till en nivå nära originalet.
JADX — den mest populära dekompilatorn från DEX till Java. Den återställer klassnamn, metoder, fält och större delen av logiken. apktool dekompilerar DEX till smali-kod (Dalvik-assembler) — en lågnivårepresentation nära de ursprungliga instruktionerna. Bytecode Viewer kombinerar flera dekompilatorer i ett gränssnitt.
Obfuskering med R8/ProGuard — första försvarslinjen: klass- och metodnamn blir oläsliga. DexGuard — kommersiellt verktyg med ytterligare metoder: strängkryptering, integritetskontroll, anti-tamper. Obfuskering på Control Flow-nivå (O-LLVM) ändrar kodstrukturen, bevarar funktionaliteten men gör analys mycket svårare.
Vanliga frågor
DEX använder registerarkitektur istället för JVM:s stackbaserade, har mer kompakt format (30% mindre), slår samman alla .class-filer i en fil med en enhetlig konstant pool och använder 16-bitars index istället för 8-bitars.
Smali — är assembler för DEX-bytekod. Varje DEX-instruktion har en textuell representation i smali-format. Verktyget baksmali konverterar DEX till smali (disassemblering), och smali assemblerar smali tillbaka till DEX.
Gradle task countMethods eller plugin dex-method-counts visar antalet metoder i varje DEX-fil. Kommandot adb shell med dumpsys visar också statistik över laddade DEX för installerade applikationer.
Ja, på enheter med Android upp till 8.0 saktar flera DEX ned starten av applikationen eftersom varje ytterligare fil laddas separat. På ART med Android 8.0+ är skillnaden minimal tack vare kompilering av dex2oat till en enda .oat-fil.
Ja, det finns projekt som dexplorer och Android-kompatibla JVM-implementationer som kan köra DEX-bytekod utanför Android. De flesta DEX-filer använder dock Android API, vilket gör dem olämpliga för körning på en vanlig JVM.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också