DEX: ce este, structura și principiul de funcționare a bytecodului

Autor: IT Sectr Publicat: 2026-04-15 Timp de citire: 8 min

DEX (Dalvik Executable) este formatul de bytecod în care se compilează codul sursă al aplicațiilor Android în Java și Kotlin. Fișierele DEX sunt executate de mașina virtuală Dalvik (până la Android 4.4) sau Android Runtime (ART, începând cu Android 5.0). Conform datelor Android Open Source Project, 2026, formatul DEX asigură în medie o reprezentare 30% mai compactă a codului în comparație cu bytecodul standard JVM.

Principalele puncte

  • DEX — format de bytecod pentru Android, executat pe Dalvik sau ART.
  • Compactitate — DEX ocupă cu 30% mai puțin spațiu decât bytecodul standard Java.
  • Multidex — mecanism pentru depășirea limitei de 65536 de metode într-un singur fișier DEX.
  • ART — Android Runtime, care a înlocuit Dalvik, compilează DEX în cod nativ la instalare.
  • D8 — compilator modern Java/Kotlin în DEX, care l-a înlocuit pe DX din 2018.

Ce este DEX și de ce este necesar

DEX (Dalvik Executable) este un format de bytecod proiectat special pentru dispozitivele mobile Android. Spre deosebire de bytecodul standard Java (fișiere .class), DEX este optimizat pentru resurse limitate: mai puțină memorie, dimensiune mai mică și încărcare mai rapidă a claselor.

De la Java la DEX

Codul sursă în Java sau Kotlin este compilat de javac/kotlinc în fișiere .class standard (bytecod Java). Apoi instrumentul d8 (sau anterior dx) convertește .class într-unul sau mai multe fișiere DEX. Această conversie nu este o simplă reambalare — d8 efectuează optimizări: îmbină pool-urile de constante, rescrie instrucțiunile în arhitectura pe registre și elimină datele duplicate.

Caracteristici arhitecturale

DEX utilizează arhitectura pe registre (spre deosebire de arhitectura pe stivă a JVM). Fiecare metodă are un număr fix de registre (până la 65536). Instrucțiunile DEX sunt mai scurte — în medie 2 octeți față de 1–4 octeți în JVM. Acest lucru oferă un cod mai compact: o aplicație tipică se reduce de la 10–15 MB .class la 4–6 MB .dex.

Structura fișierului DEX: secțiuni și antet

Fișierul DEX are o structură binară strict definită. Fiecare fișier începe cu un antet și conține mai multe secțiuni care se referă unele la altele prin offset-uri.

SecțiuneScop
headerAntet: magic, sumă de control, semnătură, dimensiuni și offset-uri ale secțiunilor
string_idsTabel de șiruri: nume de clase, metode, câmpuri
type_idsTipuri: referințe la identificatorii de șiruri ale tipurilor
proto_idsPrototipuri de metode: tipul returnat și parametrii
field_idsCâmpuri ale claselor: clasă, tip, nume
method_idsMetode: clasă, prototip, nume
class_defsDefiniții de clase: flag-uri, superclass, interfețe, offset-uri ale datelor
dataDatele efective: codul metodelor, adnotări, informații de debug

Antetul DEX

Numărul magic DEX — `dex\n035\0` (versiunea 035). Alte versiuni: 036, 037, 038 (pentru Android 8.0+). Antetul de dimensiune 0x70 octeți conține suma de control SHA-1 și offset-urile tuturor secțiunilor. Validarea antetului — primul pas la încărcarea DEX de către mașina virtuală.

Pool-uri de constante

string_ids, type_ids, proto_ids, field_ids, method_ids — sunt tabele indexate. În locul stocării numelor complete în codul metodei, se utilizează un index de 4 octeți. Aceasta este optimizarea cheie: dacă o clasă este menționată de 100 de ori, numele său este stocat o singură dată în string_ids. dex2oat la compilarea ART optimizează suplimentar aceste tabele.

Procesul de compilare Java și Kotlin în DEX

Procesul de transformare a codului sursă în DEX constă din mai multe etape. Lanțul modern folosește compilatorul D8, care l-a înlocuit pe DX în 2018 cu Android Gradle Plugin 3.2.

Etapa 1: Compilarea în .class

javac (pentru Java) sau kotlinc (pentru Kotlin) compilează codul sursă în fișiere .class. Fiecare clasă — un fișier .class separat în bytecod Java. În această etapă se efectuează verificarea tipurilor, generarea metodelor de punte și încorporarea constantelor.

Etapa 2: Compilarea D8

D8 primește toate fișierele .class și le transformă în bytecod DEX. D8 efectuează mai multe optimizări: elimină argumentele neutilizate ale metodelor, îmbină pool-urile de constante din diferite .class într-un singur pool global DEX, convertește instrucțiunile pe stivă JVM în instrucțiuni pe registre Dalvik.

kotlin
// Codul sursă Kotlin
data class User(
    val name: String,
    val email: String
)

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

După compilarea D8, acest cod se transformă în instrucțiuni compacte DEX: const-string pentru încărcarea unui șir, iget-object pentru accesarea unui câmp al obiectului, invoke-virtual pentru apelarea StringBuilder.append.

D8 vs DX

D8 funcționează de 2–3 ori mai rapid decât DX, generează un DEX mai compact (cu 5–10%) și optimizează mai bine construcțiile specifice Kotlin (funcții inline, lambda). DX a fost declarat deprecated din 2018 și eliminat din Android Gradle Plugin 8.0.

Dalvik vs ART: cum s-a schimbat execuția DEX

Execuția codului DEX în Android a trecut prin două etape: mașina virtuală originală Dalvik (Android 2.2–4.4) și Android Runtime ART (Android 5.0+). Diferența în abordarea compilării este fundamentală.

Dalvik VM: compilare JIT

Dalvik utiliza compilarea Just-In-Time (JIT): bytecodul DEX era interpretat, iar metodele frecvent apelate erau compilate în cod nativ pe loc. Avantaj — instalare rapidă. Dezavantaj — pornire mai lentă și consum constant de CPU pentru JIT.

ART: compilare AOT

ART (Android Runtime) compilează DEX în cod nativ la instalarea aplicației prin dex2oat. Aceasta este o abordare Ahead-Of-Time (AOT): instalarea durează mai mult, dar pornirea este mai rapidă și consumul de energie mai mic. Din Android 7.0 ART utilizează o abordare hibridă — AOT + JIT + Profile Guided Optimization.

dex2oat: conversia la instalare

Instrumentul dex2oat rulează la instalarea sau actualizarea aplicației. Acesta compilează DEX într-un fișier ELF cu cod nativ pentru arhitectura dispozitivului. Rezultatul — fișierele .oat și .art în directorul /data/dalvik-cache/. Google îmbunătățește constant dex2oat: pe Android 14 a fost adăugată optimizarea pentru dispozitivele pliabile.

Multidex: depășirea limitei de 64K metode

Limitarea la 65536 de metode per fișier DEX — o moștenire a arhitecturii Dalvik. Câmpul method_ids din antetul DEX ocupă 4 octeți, ceea ce oferă maximum 2^16 = 65536 de referințe unice. Aplicațiile moderne cu Google Play Services, Firebase și alte SDK-uri depășesc ușor această limită.

Mecanismul Multidex

Multidex este un mecanism de împărțire a codului în mai multe fișiere DEX. Fișierul principal classes.dex conține punctele de intrare (clasa Application, Activity-urile principale), restul — classes2.dex, classes3.dex și așa mai departe. La pornire, clasele din DEX-urile suplimentare sunt încărcate prin DexClassLoader.

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

// Clasa Application cu suport multidex
class MyApp : Application() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

Problemele Multidex

Încărcarea DEX-urilor suplimentare în faza de pornire a aplicației poate cauza ANR (Application Not Responding) pe dispozitivele cu Android până la 5.0. Recomandare — utilizați multidex doar la necesitate și minimizați dependențele pentru a nu depăși limita.

Optimizarea DEX: ProGuard, R8 și ofuscare

Optimizarea DEX — etapa standard a construirii versiunii de release a aplicației Android. Instrumentele R8 și ProGuard reduc dimensiunea DEX, ofuscă codul și elimină clasele neutilizate.

R8 vs ProGuard

R8 — succesorul lui ProGuard, integrat în Android Gradle Plugin din 2019. R8 efectuează minificarea, ofuscarea și optimizarea într-o singură trecere, în timp ce ProGuard necesita două etape: ProGuard → D8. ProGuard este încă suportat, dar Google recomandă R8 pentru proiectele noi.

R8 elimină clasele, metodele și câmpurile neutilizate, le redenumește cu nume scurte (a, b, c), încorporează funcțiile inline și aruncă codul mort. Rezultatul — DEX se reduce cu 20–40% fără pierderea funcționalității.

Regulile R8

Configurația R8 se definește în fișierul proguard-rules.pro. Dezvoltatorul poate specifica ce clase nu trebuie redenumite (de exemplu, pentru reflecție sau serializare Gson). Firebase și alte SDK-uri furnizează propriile reguli în dependențele lor.

Decompilarea DEX: instrumente și protecție

DEX poate fi decompilat înapoi în cod Java. Aceasta este o problemă cheie de securitate a aplicațiilor Android: fără ofuscare, codul este restaurat la un nivel apropiat de original.

Instrumente de decompilare

JADX — cel mai popular decompilator DEX în Java. Acesta restaurează numele claselor, metodelor, câmpurilor și cea mai mare parte a logicii. apktool decompilează DEX în cod smali (asamblor Dalvik) — o reprezentare de nivel scăzut apropiată de instrucțiunile originale. Bytecode Viewer combină mai multe decompilatoare într-o singură interfață.

Metode de protecție

Ofuscarea R8/ProGuard — prima linie de apărare: numele claselor și metodelor devin ilizibile. DexGuard — instrument comercial cu metode suplimentare: criptarea șirurilor, verificarea integrității, anti-tamper. Ofuscarea la nivel de Control Flow (O-LLVM) modifică structura codului, păstrându-i funcționalitatea, dar făcând analiza mult mai dificilă.

Întrebări frecvente

Cu ce se diferențiază DEX de bytecodul Java?

DEX utilizează arhitectura pe registre în locul celei pe stivă a JVM, are un format mai compact (cu 30% mai mic), îmbină toate fișierele .class într-un singur fișier cu un pool unic de constante și utilizează indecși pe 16 biți în loc de 8 biți.

Ce este smali?

Smali — este asamblorul bytecodului DEX. Fiecare instrucțiune DEX are o reprezentare textuală în format smali. Instrumentul baksmali convertește DEX în smali (dezasamblare), iar smali asamblează smali înapoi în DEX.

Cum se verifică numărul de metode în DEX?

Gradle task countMethods sau pluginul dex-method-counts arată numărul de metode în fiecare fișier DEX. Comanda adb shell cu dumpsys afișează, de asemenea, statisticile DEX-urilor încărcate pentru aplicațiile instalate.

Numărul de DEX influențează performanța?

Da, pe dispozitivele cu Android până la 8.0, DEX-urile multiple încetinesc pornirea aplicației, deoarece fiecare fișier suplimentar este încărcat separat. Pe ART cu Android 8.0+ diferența este minimă datorită compilării dex2oat într-un singur fișier .oat.

Se poate rula DEX fără Android?

Da, există proiecte precum dexplorer și implementări JVM compatibile cu Android care pot executa bytecod DEX în afara Android. Cu toate acestea, majoritatea fișierelor DEX utilizează Android API, ceea ce le face nepotrivite pentru rularea pe o JVM obișnuită.

Rezumat

  • DEX — format de bytecod Android cu arhitectură pe registre și reprezentare compactă a codului.
  • Structura include antet, tabele de identificatori și secțiunea de date cu instrucțiuni.
  • Compilarea în DEX se realizează prin D8: .class → DEX cu optimizări și îmbinarea pool-urilor de constante.
  • ART compilează DEX în cod nativ la instalare (AOT), accelerând pornirea aplicației.
  • Multidex — soluția problemei limitei de 65536 de metode prin împărțirea în mai multe fișiere DEX.
  • Optimizarea — R8 reduce DEX cu 20–40%, ofuscă numele și elimină codul mort.
  • Protecția — ofuscarea R8/ProGuard, DexGuard și O-LLVM previn decompilarea DEX.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și