DEX (Dalvik Executable) ist ein Bytecode-Format, in das der Quellcode von Android-Anwendungen in Java und Kotlin kompiliert wird. DEX-Dateien werden von der virtuellen Dalvik-Maschine (bis Android 4.4) oder der Android Runtime (ART, ab Android 5.0) ausgeführt. Laut Android Open Source Project, 2026 bietet das DEX-Format im Durchschnitt eine um 30% kompaktere Codedarstellung im Vergleich zum standardmäßigen JVM-Java-Bytecode.
Wichtige Punkte
DEX (Dalvik Executable) ist ein Bytecode-Format, das speziell für Android-Mobilgeräte entwickelt wurde. Im Gegensatz zum standardmäßigen Java-Bytecode (.class-Dateien) ist DEX für begrenzte Ressourcen optimiert: weniger Speicher, kleinere Größe und schnelleres Klassenladen.
Quellcode in Java oder Kotlin wird von javac/kotlinc in standardmäßige .class-Dateien (Java-Bytecode) kompiliert. Anschließend konvertiert das Werkzeug d8 (oder früher dx) .class in eine oder mehrere DEX-Dateien. Diese Konvertierung ist keine einfache Neuverpackung — d8 führt Optimierungen durch: Zusammenführen von Konstantenpools, Umschreiben von Anweisungen in eine Registerarchitektur und Entfernen doppelter Daten.
DEX verwendet eine registerbasierte Architektur (im Gegensatz zur stapelbasierten JVM). Jede Methode hat eine feste Anzahl von Registern (bis zu 65536). DEX-Anweisungen sind kürzer — durchschnittlich 2 Bytes gegenüber 1–4 Bytes in der JVM. Dies führt zu kompakterem Code: Eine typische Anwendung schrumpft von 10–15 MB .class auf 4–6 MB .dex.
Eine DEX-Datei hat eine streng definierte binäre Struktur. Jede Datei beginnt mit einem Header und enthält mehrere Abschnitte, die über Offsets aufeinander verweisen.
| Abschnitt | Zweck |
|---|---|
| header | Header: Magic, Prüfsumme, Signatur, Abschnittsgrößen und Offsets |
| string_ids | Zeichenkettentabelle: Klassen-, Methoden- und Feldnamen |
| type_ids | Typen: Verweise auf Typ-String-Identifikatoren |
| proto_ids | Methodenprototypen: Rückgabetyp und Parameter |
| field_ids | Klassenfelder: Klasse, Typ, Name |
| method_ids | Methoden: Klasse, Prototyp, Name |
| class_defs | Klassendefinitionen: Flags, Superklasse, Schnittstellen, Daten-Offsets |
| data | Tatsächliche Daten: Methodencode, Annotationen, Debug-Informationen |
Die magische Zahl von DEX ist `dex\n035\0` (Version 035). Andere Versionen: 036, 037, 038 (für Android 8.0+). Der Header ist 0x70 Bytes groß und enthält eine SHA-1-Prüfsumme und Offsets aller Abschnitte. Die Header-Validierung ist der erste Schritt beim Laden einer DEX durch die virtuelle Maschine.
string_ids, type_ids, proto_ids, field_ids, method_ids — dies sind indizierte Tabellen. Anstatt vollständige Namen im Methodencode zu speichern, wird ein 4-Byte-Index verwendet. Dies ist eine entscheidende Optimierung: Wenn eine Klasse 100 Mal referenziert wird, wird ihr Name einmal in string_ids gespeichert. dex2oat optimiert diese Tabellen während der ART-Kompilierung weiter.
Der Prozess der Umwandlung von Quellcode in DEX besteht aus mehreren Phasen. Die moderne Toolchain verwendet den D8-Compiler, der DX im Jahr 2018 mit Android Gradle Plugin 3.2 ablöste.
javac (für Java) oder kotlinc (für Kotlin) kompilieren den Quellcode in .class-Dateien. Jede Klasse ist eine separate .class-Datei in Java-Bytecode. In dieser Phase werden Typprüfung, Generierung von Bridge-Methoden und Inlining von Konstanten durchgeführt.
D8 nimmt alle .class-Dateien und wandelt sie in DEX-Bytecode um. D8 führt mehrere Optimierungen durch: Entfernen ungenutzter Methodenargumente, Zusammenführen von Konstantenpools aus verschiedenen .class-Dateien in einen globalen DEX-Pool und Konvertieren von JVM-Stapelanweisungen in Dalvik-Registeranweisungen.
// Kotlin-Quellcode
data class User(
val name: String,
val email: String
)
fun greet(user: User): String {
return "Hello, ${user.name}!"
}
Nach der D8-Kompilierung wird dieser Code in kompakte DEX-Anweisungen umgewandelt: const-string zum Laden von Zeichenketten, iget-object für den Zugriff auf Objektfelder, invoke-virtual zum Aufrufen von StringBuilder.append.
D8 ist 2–3 Mal schneller als DX, erzeugt kompakteres DEX (5–10% kleiner) und optimiert Kotlin-spezifische Konstrukte (Inline-Funktionen, Lambdas) besser. DX wurde 2018 für veraltet erklärt und aus Android Gradle Plugin 8.0 entfernt.
Die Ausführung von DEX-Code in Android durchlief zwei Phasen: die ursprüngliche virtuelle Dalvik-Maschine (Android 2.2–4.4) und die Android Runtime ART (Android 5.0+). Der Unterschied im Kompilierungsansatz ist grundlegend.
Dalvik verwendete Just-In-Time (JIT)-Kompilierung: DEX-Bytecode wurde interpretiert und häufig aufgerufene Methoden spontan in nativen Code kompiliert. Vorteil — schnelle Installation. Nachteil — langsamere Startzeit und ständige CPU-Belastung durch JIT.
ART (Android Runtime) kompiliert DEX während der Installation der Anwendung über dex2oat in nativen Code. Dies ist ein Ahead-Of-Time (AOT)-Ansatz: Die Installation dauert länger, aber der Start ist schneller und der Stromverbrauch geringer. Seit Android 7.0 verwendet ART einen hybriden Ansatz — AOT + JIT + profilgesteuerte Optimierung.
Das Werkzeug dex2oat wird beim Installieren oder Aktualisieren einer Anwendung ausgeführt. Es kompiliert DEX in eine ELF-Datei mit nativem Code für die Gerätearchitektur. Das Ergebnis — .oat- und .art-Dateien im Verzeichnis /data/dalvik-cache/. Google verbessert dex2oat kontinuierlich: In Android 14 wurden Optimierungen für faltbare Geräte hinzugefügt.
Das Limit von 65536 Methoden pro DEX-Datei ist ein Erbe der Dalvik-Architektur. Das Feld method_ids im DEX-Header belegt 4 Bytes und ergibt maximal 2^16 = 65536 eindeutige Referenzen. Moderne Anwendungen mit Google Play Services, Firebase und anderen SDKs überschreiten dieses Limit leicht.
Multidex ist ein Mechanismus zur Aufteilung von Code auf mehrere DEX-Dateien. Die Hauptdatei classes.dex enthält die Einstiegspunkte (Application-Klasse, Haupt-Activity), die restlichen sind classes2.dex, classes3.dex usw. Beim Start werden Klassen aus zusätzlichen DEX-Dateien über DexClassLoader geladen.
// build.gradle.kts — Aktivierung von Multidex
android {
defaultConfig {
multiDexEnabled = true
}
}
// Application-Klasse mit Multidex-Unterstützung
class MyApp : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
}
Das Laden zusätzlicher DEX-Dateien beim Start der Anwendung kann auf Geräten mit Android vor 5.0 zu ANR (Application Not Responding) führen. Empfehlung — Multidex nur bei Bedarf verwenden und Abhängigkeiten minimieren, um das Limit nicht zu überschreiten.
Die Optimierung von DEX ist ein Standardschritt beim Erstellen einer Android-Release-Anwendung. Die Werkzeuge R8 und ProGuard reduzieren die DEX-Größe, verschleiern Code und entfernen ungenutzte Klassen.
R8 ist der Nachfolger von ProGuard, der seit 2019 in Android Gradle Plugin integriert ist. R8 führt Minimierung, Verschleierung und Optimierung in einem einzigen Durchlauf durch, während ProGuard zwei Phasen benötigte: ProGuard → D8. ProGuard wird weiterhin unterstützt, aber Google empfiehlt R8 für neue Projekte.
R8 entfernt ungenutzte Klassen, Methoden und Felder, benennt sie in kurze Namen um (a, b, c), bindet Inline-Funktionen ein und entfernt toten Code. Das Ergebnis — DEX wird um 20–40% reduziert, ohne Funktionalität zu verlieren.
Die R8-Konfiguration wird in der Datei proguard-rules.pro festgelegt. Der Entwickler kann angeben, welche Klassen nicht umbenannt werden dürfen (z. B. für Reflexion oder Gson-Serialisierung). Firebase und andere SDKs liefern eigene Regeln in ihren Abhängigkeiten.
DEX kann zurück in Java-Code dekompiliert werden. Dies ist eine wichtige Sicherheitsfrage für Android-Anwendungen: Ohne Verschleierung wird Code auf ein dem Original nahes Niveau wiederhergestellt.
JADX ist der beliebteste DEX-zu-Java-Dekompiler. Er stellt Klassennamen, Methoden, Felder und den Großteil der Logik wieder her. apktool dekompiliert DEX in Smali-Code (Dalvik-Assembler) — eine niedrige Darstellung nahe den ursprünglichen Anweisungen. Bytecode Viewer vereint mehrere Dekompilierer in einer Oberfläche.
Die Verschleierung mit R8/ProGuard ist die erste Verteidigungslinie: Klassen- und Methodennamen werden unlesbar. DexGuard ist ein kommerzielles Werkzeug mit zusätzlichen Methoden: Zeichenkettenverschlüsselung, Integritätsprüfung, Anti-Manipulation. Die Kontrollflussverschleierung (O-LLVM) ändert die Codestruktur unter Beibehaltung der Funktionalität und erschwert die Analyse erheblich.
Häufig gestellte Fragen
DEX verwendet eine registerbasierte Architektur anstelle der stapelbasierten JVM, hat ein kompakteres Format (30% kleiner), fasst alle .class-Dateien in einer Datei mit einem einheitlichen Konstantenpool zusammen und verwendet 16-Bit-Indizes anstelle von 8-Bit-Indizes.
Smali ist ein Assembler für DEX-Bytecode. Jede DEX-Anweisung hat eine Textdarstellung im Smali-Format. Das Werkzeug baksmali konvertiert DEX in Smali (Disassemblierung), und Smali assembliert Smali zurück in DEX.
Der Gradle-Task countMethods oder das Plugin dex-method-counts zeigen die Anzahl der Methoden in jeder DEX-Datei. Der Befehl adb shell mit dumpsys zeigt ebenfalls Statistiken der geladenen DEX-Dateien für installierte Anwendungen.
Ja, auf Geräten mit Android vor 8.0 verlangsamen mehrere DEX-Dateien den Anwendungsstart, da jede zusätzliche Datei separat geladen wird. Auf ART mit Android 8.0+ ist der Unterschied dank der dex2oat-Kompilierung in eine einzelne .oat-Datei minimal.
Ja, es gibt Projekte wie dexplorer und Android-kompatible JVM-Implementierungen, die DEX-Bytecode außerhalb von Android ausführen können. Die meisten DEX-Dateien verwenden jedoch die Android-API, was sie für die Ausführung auf einer Standard-JVM ungeeignet macht.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch