DEX: vad är det, struktur och funktionsprincip för bytekod

Författare: IT Sectr Publicerad: 2026-04-15 Lästid: 8 min

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 — bytekodsformat för Android, exekverbart på Dalvik eller ART.
  • Kompakthet — DEX tar 30% mindre plats än standard Java-bytekod.
  • Multidex — mekanism för att kringgå gränsen på 65536 metoder i en DEX-fil.
  • ART — Android Runtime, som ersatte Dalvik, kompilerar DEX till native-kod vid installation.
  • D8 — modern kompilator från Java/Kotlin till DEX, som ersatte DX från 2018.

Vad är DEX och varför behövs det

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.

Från Java till DEX

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.

Arkitektoniska egenskaper

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.

Struktur för en DEX-fil: sektioner och rubrik

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.

SektionSyfte
headerRubrik: magic, kontrollsumma, signatur, storlekar och offsetar för sektioner
string_idsSträngtabell: namn på klasser, metoder, fält
type_idsTyper: referenser till strängidentifierare för typer
proto_idsMetodprototyper: returtyp och parametrar
field_idsKlassfält: klass, typ, namn
method_idsMetoder: klass, prototyp, namn
class_defsKlassdefinitioner: flaggor, superclass, gränssnitt, dataoffsetar
dataFaktisk data: metodkod, annoteringar, debug-information

DEX-rubrik

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.

Konstanta pooler

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.

Kompileringsprocessen från Java och Kotlin till DEX

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.

Steg 1: Kompilering till .class

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.

Steg 2: D8-kompilering

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
// 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 vs DX

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.

Dalvik vs ART: hur exekvering av DEX förändrades

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 VM: JIT-kompilering

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: AOT-kompilering

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.

dex2oat: konvertering vid installation

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.

Multidex: övervinna gränsen på 64K metoder

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-mekanismen

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.

kotlin
// 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)
    }
}

Problem med Multidex

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: ProGuard, R8 och obfuskering

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 vs ProGuard

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.

R8-regler

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.

Dekompilering av DEX: verktyg och skydd

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.

Dekompileringsverktyg

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.

Skyddsmetoder

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

Vad skiljer DEX från Java-bytekod?

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.

Vad är smali?

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.

Hur kontrollerar man antalet metoder i 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.

Påverkar antalet DEX prestanda?

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.

Kan DEX köras utan Android?

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

  • DEX — Android-bytekodsformat med registerarkitektur och kompakt kodrepresentation.
  • Struktur omfattar rubrik, identifierartabeller och en datasektion med instruktioner.
  • Kompilering till DEX sker via D8: .class → DEX med optimeringar och sammanslagning av konstanta pooler.
  • ART kompilerar DEX till native-kod vid installation (AOT), vilket påskyndar applikationsstart.
  • Multidex — lösning på problemet med gränsen på 65536 metoder genom uppdelning i flera DEX-filer.
  • Optimering — R8 minskar DEX med 20–40%, obfuskerar namn och tar bort död kod.
  • Skydd — obfuskering med R8/ProGuard, DexGuard och O-LLVM förhindrar dekompilering av DEX.

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.

Diskutera projektet

Läs också