A DEX (Dalvik Executable) az a bájtkód formátum, amelybe az Android-alkalmazások Java és Kotlin forráskódja lefordításra kerül. A DEX fájlokat a Dalvik virtuális gép (Android 4.4-ig) vagy az Android Runtime (ART, Android 5.0-tól) hajtja végre. A Android Open Source Project, 2026 adatai szerint a DEX formátum átlagosan 30%-kal tömörebb kódábrázolást biztosít a szabványos JVM bájtkódhoz képest.
Főbb pontok
A DEX (Dalvik Executable) egy kifejezetten Android mobileszközökhöz tervezett bájtkód formátum. A szabványos Java bájtkóddal (.class fájlok) ellentétben a DEX korlátozott erőforrásokra van optimalizálva: kevesebb memória, kisebb méret és gyorsabb osztálybetöltés.
A Java vagy Kotlin forráskódot a javac/kotlinc szabványos .class fájlokba (Java bájtkód) fordítja. Ezután a d8 (vagy korábban dx) eszköz a .class fájlokat egy vagy több DEX fájllá alakítja. Ez az átalakítás nem egyszerű átcsomagolás — a d8 optimalizálásokat végez: egyesíti a konstans poolokat, átírja az utasításokat regiszter architektúrába, és eltávolítja a duplikált adatokat.
A DEX regiszter architektúrát használ (ellentétben a JVM veremalapú architektúrájával). Minden metódusnak fix számú regisztere van (legfeljebb 65536). A DEX utasítások rövidebbek — átlagosan 2 bájt a JVM 1–4 bájtjával szemben. Ez tömörebb kódot eredményez: egy tipikus alkalmazás 10–15 MB .class-ról 4–6 MB .dex-re csökken.
A DEX fájl szigorúan meghatározott bináris szerkezettel rendelkezik. Minden fájl fejléccel kezdődik, és több szekciót tartalmaz, amelyek egymásra offset-eken keresztül hivatkoznak.
| Szekció | Cél |
|---|---|
| header | Fejléc: magic, ellenőrző összeg, aláírás, szekciók méretei és offset-jei |
| string_ids | Karakterlánc tábla: osztályok, metódusok, mezők nevei |
| type_ids | Típusok: hivatkozások a típusok karakterlánc-azonosítóira |
| proto_ids | Metódus prototípusok: visszatérési típus és paraméterek |
| field_ids | Osztálymezők: osztály, típus, név |
| method_ids | Metódusok: osztály, prototípus, név |
| class_defs | Osztálydefiníciók: jelzők, superclass, interfészek, adat offset-ek |
| data | Tényleges adatok: metóduskód, annotációk, debug információ |
A DEX varázsszáma — `dex\n035\0` (035-ös verzió). Egyéb verziók: 036, 037, 038 (Android 8.0+ esetén). A 0x70 bájt méretű fejléc SHA-1 ellenőrző összeget és az összes szekció offset-jeit tartalmazza. A fejléc érvényesítése — az első lépés a DEX virtuális gép általi betöltésekor.
A string_ids, type_ids, proto_ids, field_ids, method_ids — indexelt táblák. A teljes nevek metóduskódban való tárolása helyett 4 bájtos indexet használunk. Ez a kulcsfontosságú optimalizálás: ha egy osztály 100-szor szerepel, a neve egyszer kerül tárolásra a string_ids-ben. A dex2oat az ART fordítás során tovább optimalizálja ezeket a táblákat.
A forráskód DEX-be alakításának folyamata több szakaszból áll. A modern lánc a D8 fordítót használja, amely 2018-ban az Android Gradle Plugin 3.2-vel váltotta fel a DX-et.
A javac (Java esetén) vagy kotlinc (Kotlin esetén) a forráskódot .class fájlokba fordítja. Minden osztály — egy külön .class fájl Java bájtkódban. Ebben a szakaszban típusellenőrzés, hídmetódusok generálása és konstansok beágyazása történik.
A D8 az összes .class fájlt átveszi, és DEX bájtkóddá alakítja. A D8 több optimalizálást is végez: eltávolítja a nem használt metódus argumentumokat, egyesíti a konstans poolokat különböző .class fájlokból egy globális DEX poolba, átalakítja a JVM veremutasításokat Dalvik regiszterutasításokká.
// Kotlin forráskód
data class User(
val name: String,
val email: String
)
fun greet(user: User): String {
return "Hello, ${user.name}!"
}
A D8 fordítás után ez a kód kompakt DEX utasításokká alakul: const-string egy karakterlánc betöltéséhez, iget-object egy objektum mező eléréséhez, invoke-virtual a StringBuilder.append meghívásához.
A D8 2–3-szor gyorsabb, mint a DX, tömörebb DEX-et generál (5–10%-kal), és jobban optimalizálja a Kotlin-specifikus szerkezeteket (inline függvények, lambda). A DX 2018 óta elavultnak (deprecated) minősül, és eltávolításra került az Android Gradle Plugin 8.0-ból.
A DEX kód végrehajtása Androidban két szakaszon ment keresztül: az eredeti Dalvik virtuális gép (Android 2.2–4.4) és az Android Runtime ART (Android 5.0+). A fordítási megközelítés különbsége alapvető.
A Dalvik Just-In-Time (JIT) fordítást használt: a DEX bájtkód értelmezésre került, a gyakran hívott metódusok pedig menet közben natív kódba lettek fordítva. Előny — gyors telepítés. Hátrány — lassabb indítás és állandó CPU terhelés a JIT miatt.
Az ART (Android Runtime) az alkalmazás telepítésekor a dex2oat segítségével natív kódba fordítja a DEX-et. Ez az Ahead-Of-Time (AOT) megközelítés: a telepítés tovább tart, de az indítás gyorsabb és az energiafogyasztás kisebb. Android 7.0 óta az ART hibrid megközelítést használ — AOT + JIT + Profile Guided Optimization.
A dex2oat eszköz az alkalmazás telepítésekor vagy frissítésekor fut. A DEX-et ELF fájllá fordítja natív kóddal az eszköz architektúrájához. Eredmény — .oat és .art fájlok a /data/dalvik-cache/ könyvtárban. A Google folyamatosan fejleszti a dex2oat-ot: Android 14-ben optimalizálás került hozzáadásra a hajlítható eszközökhöz.
A 65536 metódus korlátozása egy DEX fájlban — a Dalvik architektúra öröksége. A method_ids mező a DEX fejlécben 4 bájtot foglal, ami maximum 2^16 = 65536 egyedi hivatkozást tesz lehetővé. A modern alkalmazások Google Play Services-szel, Firebase-zel és más SDK-kkal könnyen túllépik ezt a korlátot.
A Multidex egy mechanizmus a kód több DEX fájlra osztására. A fő classes.dex tartalmazza a belépési pontokat (Application osztály, fő Activity), a többi — classes2.dex, classes3.dex és így tovább. Indításkor a kiegészítő DEX-ekből származó osztályok a DexClassLoader segítségével töltődnek be.
// build.gradle.kts — multidex engedélyezése
android {
defaultConfig {
multiDexEnabled = true
}
}
// Application osztály multidex támogatással
class MyApp : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
}
A kiegészítő DEX-ek betöltése az alkalmazás indítási szakaszában ANR-t (Application Not Responding) okozhat Android 5.0-ig terjedő eszközökön. Javaslat — csak szükség esetén használjon multidex-et, és minimalizálja a függőségeket, hogy ne lépje túl a korlátot.
A DEX optimalizálás — a release Android alkalmazás készítésének szabványos szakasza. Az R8 és ProGuard eszközök csökkentik a DEX méretét, obfuszkálják a kódot, és eltávolítják a nem használt osztályokat.
Az R8 — a ProGuard utódja, 2019 óta beépítve az Android Gradle Plugin-be. Az R8 egy menetben végzi el a minifikációt, obfuszkációt és optimalizálást, míg a ProGuard két szakaszt igényelt: ProGuard → D8. A ProGuard továbbra is támogatott, de a Google az R8-at ajánlja új projektekhez.
Az R8 eltávolítja a nem használt osztályokat, metódusokat és mezőket, rövid nevekre (a, b, c) nevezi át őket, beágyazza az inline függvényeket, és kidobja a halott kódot. Eredmény — a DEX 20–40%-kal csökken a funkcionalitás elvesztése nélkül.
Az R8 konfigurációja a proguard-rules.pro fájlban van megadva. A fejlesztő megadhatja, mely osztályok nem nevezhetők át (például reflexió vagy Gson szerializáció esetén). A Firebase és más SDK-k saját szabályokat szállítanak a függőségeikben.
A DEX visszafordítható Java kóddá. Ez az Android alkalmazások biztonságának kulcskérdése: obfuszkáció nélkül a kód az eredetihez közeli szinten állítható helyre.
A JADX — a legnépszerűbb DEX dekompilátor Java-ba. Visszaállítja az osztályneveket, metódusokat, mezőket és a logika nagy részét. Az apktool DEX-et smali kóddá (Dalvik assembler) dekompilálja — alacsony szintű reprezentáció, közel az eredeti utasításokhoz. A Bytecode Viewer több dekompilátort egyesít egy felületen.
Az R8/ProGuard obfuszkáció — az első védelmi vonal: az osztály- és metódusnevek olvashatatlanná válnak. A DexGuard — kereskedelmi eszköz további módszerekkel: karakterlánc-titkosítás, integritás-ellenőrzés, anti-tamper. Az obfuszkáció Control Flow szinten (O-LLVM) megváltoztatja a kód szerkezetét, megtartva funkcionalitását, de az elemzést sokkal nehezebbé téve.
Gyakran ismételt kérdések
A DEX regiszter architektúrát használ a JVM veremalapú helyett, tömörebb formátummal rendelkezik (30%-kal kisebb), egyesíti az összes .class fájlt egy fájlba egységes konstans pool-lal, és 16 bites indexeket használ 8 bites helyett.
A smali — a DEX bájtkód assemblerje. Minden DEX utasításnak van szöveges megjelenítése smali formátumban. A baksmali eszköz DEX-et smali-vé alakít (visszafejtés), a smali pedig smali-ból DEX-et készít.
A Gradle countMethods task vagy a dex-method-counts plugin mutatja a metódusok számát minden DEX fájlban. Az adb shell parancs a dumpsys-szel szintén megjeleníti a betöltött DEX-ek statisztikáját a telepített alkalmazásokhoz.
Igen, Android 8.0-ig terjedő eszközökön a több DEX lassítja az alkalmazás indítását, mivel minden további fájl külön töltődik be. ART-on Android 8.0+ esetén a különbség minimális a dex2oat egyetlen .oat fájlba történő fordításának köszönhetően.
Igen, léteznek olyan projektek, mint a dexplorer és Android-kompatibilis JVM implementációk, amelyek képesek DEX bájtkódot futtatni Androidon kívül. Azonban a legtöbb DEX fájl az Android API-t használja, ami alkalmatlanná teszi őket szokványos JVM-en való futtatásra.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is