\n DEX (Dalvik Executable) to format bajtkodu, do którego kompilowany jest kod źródłowy aplikacji Android w Javie i Kotlinie. Pliki DEX są wykonywane przez maszynę wirtualną Dalvik (do Androida 4.4) lub Android Runtime (ART, od Androida 5.0). Według danych Android Open Source Project, 2026, format DEX zapewnia średnio 30% bardziej kompaktowe przedstawienie kodu w porównaniu ze standardowym bajtkodem JVM.\n
\nNajważniejsze informacje
\nDEX (Dalvik Executable) to format bajtkodu zaprojektowany specjalnie dla urządzeń mobilnych Android. W przeciwieństwie do standardowego bajtkodu Java (pliki .class), DEX jest zoptymalizowany pod kątem ograniczonych zasobów: mniej pamięci, mniejszy rozmiar i szybsze ładowanie klas.
\n\nKod źródłowy w Java lub Kotlin jest kompilowany przez javac/kotlinc do standardowych plików .class (bajtkod Java). Następnie narzędzie d8 (lub wcześniej dx) konwertuje .class na jeden lub kilka plików DEX. Ta konwersja to nie zwykłe przepakowanie — d8 wykonuje optymalizacje: łączy pulę stałych, przepisuje instrukcje do architektury rejestrowej i usuwa zduplikowane dane.
\n\nDEX wykorzystuje architekturę rejestrową (w przeciwieństwie do stosowej JVM). Każda metoda ma stałą liczbę rejestrów (do 65536). Instrukcje DEX są krótsze — średnio 2 bajty wobec 1–4 bajtów w JVM. Daje to bardziej kompaktowy kod: typowa aplikacja zmniejsza się z 10–15 MB .class do 4–6 MB .dex.
\nPlik DEX ma ściśle określoną binarną strukturę. Każdy plik zaczyna się od nagłówka i zawiera kilka sekcji, które odwołują się do siebie poprzez przesunięcia.
\n\n| Sekcja | Przeznaczenie |
|---|---|
| header | Nagłówek: magic, suma kontrolna, podpis, rozmiary i przesunięcia sekcji |
| string_ids | Tabela ciągów: nazwy klas, metod, pól |
| type_ids | Typy: odwołania do identyfikatorów ciągów typów |
| proto_ids | Prototypy metod: typ zwracany i parametry |
| field_ids | Pola klas: klasa, typ, nazwa |
| method_ids | Metody: klasa, prototyp, nazwa |
| class_defs | Definicje klas: flagi, superclass, interfejsy, przesunięcia danych |
| data | Rzeczywiste dane: kod metod, adnotacje, informacje debug |
Magiczna liczba DEX — `dex\n035\0` (wersja 035). Inne wersje: 036, 037, 038 (dla Androida 8.0+). Nagłówek o rozmiarze 0x70 bajtów zawiera sumę kontrolną SHA-1 i przesunięcia wszystkich sekcji. Walidacja nagłówka — pierwszy krok przy ładowaniu DEX przez maszynę wirtualną.
\n\nstring_ids, type_ids, proto_ids, field_ids, method_ids — to indeksowane tabele. Zamiast przechowywania pełnych nazw w kodzie metody używany jest 4-bajtowy indeks. To kluczowa optymalizacja: jeśli klasa jest wymieniana 100 razy, jej nazwa jest przechowywana raz w string_ids. dex2oat podczas kompilacji ART dodatkowo optymalizuje te tabele.
\nProces przekształcania kodu źródłowego w DEX składa się z kilku etapów. Nowoczesny łańcuch używa kompilatora D8, który zastąpił DX w 2018 roku wraz z Android Gradle Plugin 3.2.
\n\njavac (dla Java) lub kotlinc (dla Kotlin) kompilują kod źródłowy do plików .class. Każda klasa — osobny plik .class w bajtkodzie Java. Na tym etapie wykonywane jest sprawdzanie typów, generowanie metod bridge i osadzanie stałych.
\n\nD8 przyjmuje wszystkie pliki .class i przekształca je w bajtkod DEX. D8 wykonuje kilka optymalizacji: usuwa nieużywane argumenty metod, łączy pule stałych z różnych .class w jedną globalną pulę DEX, konwertuje instrukcje stosowe JVM na rejestrowe instrukcje Dalvik.
\n\n// Kod źródłowy Kotlin
data class User(
val name: String,
val email: String
)
fun greet(user: User): String {
return "Hello, ${user.name}!"
}\n Po kompilacji D8 ten kod zamienia się w kompaktowe instrukcje DEX: const-string do załadowania ciągu, iget-object do dostępu do pola obiektu, invoke-virtual do wywołania StringBuilder.append.
\n\nD8 działa 2–3 razy szybciej niż DX, generuje bardziej kompaktowy DEX (o 5–10%) i lepiej optymalizuje konstrukcje specyficzne dla Kotlin (funkcje inline, lambda). DX został oznaczony jako deprecated od 2018 roku i usunięty z Android Gradle Plugin 8.0.
\nWykonywanie kodu DEX w Androidzie przeszło dwa etapy: oryginalna maszyna wirtualna Dalvik (Android 2.2–4.4) i Android Runtime ART (Android 5.0+). Różnica w podejściu do kompilacji jest kardynalna.
\n\nDalvik używała kompilacji Just-In-Time (JIT): bajtkod DEX był interpretowany, a często wywoływane metody były kompilowane do kodu natywnego na bieżąco. Plus — szybka instalacja. Minus — wolniejszy start i stałe obciążenie CPU przez JIT.
\n\nART (Android Runtime) kompiluje DEX do kodu natywnego podczas instalacji aplikacji przez dex2oat. To podejście Ahead-Of-Time (AOT): instalacja trwa dłużej, ale uruchomienie jest szybsze i zużycie energii mniejsze. Od Androida 7.0 ART używa hybrydowego podejścia — AOT + JIT + Profile Guided Optimization.
\n\nNarzędzie dex2oat uruchamia się podczas instalacji lub aktualizacji aplikacji. Kompiluje DEX do pliku ELF z kodem natywnym dla architektury urządzenia. Rezultat — pliki .oat i .art w katalogu /data/dalvik-cache/. Google stale ulepsza dex2oat: w Androidzie 14 dodano optymalizację dla urządzeń składanych.
\nOgraniczenie do 65536 metod na jeden plik DEX — pozostałość po architekturze Dalvik. Pole method_ids w nagłówku DEX zajmuje 4 bajty, co daje maksymalnie 2^16 = 65536 unikalnych odwołań. Nowoczesne aplikacje z Google Play Services, Firebase i innymi SDK łatwo przekraczają ten limit.
\n\nMultidex — to mechanizm podziału kodu na kilka plików DEX. Główny classes.dex zawiera punkty wejścia (klasę Application, główne Activity), pozostałe — classes2.dex, classes3.dex i tak dalej. Podczas uruchamiania klasy z dodatkowych DEX są ładowane przez DexClassLoader.
\n\n// build.gradle.kts — włączenie multidex
android {
defaultConfig {
multiDexEnabled = true
}
}
// Klasa Application z obsługą multidex
class MyApp : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
}\n Ładowanie dodatkowych DEX na etapie startu aplikacji może powodować ANR (Application Not Responding) na urządzeniach z Androidem do 5.0. Zalecenie — używać multidex tylko w razie konieczności i minimalizować zależności, aby nie przekraczać limitu.
\nOptymalizacja DEX — standardowy etap budowania wersji release aplikacji Android. Narzędzia R8 i ProGuard zmniejszają rozmiar DEX, zaciemniają kod i usuwają nieużywane klasy.
\n\nR8 — następca ProGuarda, wbudowany w Android Gradle Plugin od 2019 roku. R8 wykonuje minifikację, zaciemnianie i optymalizację w jednym przejściu, podczas gdy ProGuard wymagał dwóch etapów: ProGuard → D8. ProGuard jest nadal wspierany, ale Google zaleca R8 dla nowych projektów.
\n\nR8 usuwa nieużywane klasy, metody i pola, zmienia ich nazwy na krótkie (a, b, c), osadza funkcje inline i wyrzuca martwy kod. Rezultat — DEX zmniejsza się o 20–40% bez utraty funkcjonalności.
\n\nKonfiguracja R8 jest zadawana w pliku proguard-rules.pro. Deweloper może wskazać, których klas nie wolno zmieniać (na przykład dla refleksji lub serializacji Gson). Firebase i inne SDK dostarczają własne reguły w swoich zależnościach.
\nDEX można dekompilować z powrotem do kodu Java. To kluczowe zagadnienie bezpieczeństwa aplikacji Android: bez zaciemniania kod jest odtwarzany do poziomu bliskiego oryginałowi.
\n\nJADX — najpopularniejszy dekompilator DEX do Java. Odtwarza nazwy klas, metody, pola i większość logiki. apktool dekompiluje DEX do kodu smali (asembler Dalvik) — niskopoziomową reprezentację bliską oryginalnym instrukcjom. Bytecode Viewer łączy kilka dekompilatorów w jednym interfejsie.
\n\nZaciemnianie R8/ProGuard — pierwsza linia obrony: nazwy klas i metod stają się nieczytelne. DexGuard — komercyjne narzędzie z dodatkowymi metodami: szyfrowanie ciągów, sprawdzanie integralności, anty-tamper. Obfuscation na poziomie Control Flow (O-LLVM) zmienia strukturę kodu, zachowując jego funkcjonalność, ale znacznie utrudniając analizę.
\nCzęsto zadawane pytania
\n\nDEX używa architektury rejestrowej zamiast stosowej JVM, ma bardziej kompaktowy format (o 30% mniejszy), łączy wszystkie .class w jeden plik z jednolitą pulą stałych i używa 16-bitowych indeksów zamiast 8-bitowych.
\nSmali — to asembler bajtkodu DEX. Każda instrukcja DEX ma tekstową reprezentację w formacie smali. Narzędzie baksmali konwertuje DEX do smali (dezasemblacja), a smali składa smali z powrotem do DEX.
\nGradle task countMethods lub wtyczka dex-method-counts pokazują liczbę metod w każdym pliku DEX. Polecenie adb shell z dumpsys również wyświetla statystyki załadowanych DEX dla zainstalowanych aplikacji.
\nTak, na urządzeniach z Androidem do 8.0 wielokrotny DEX spowalnia uruchamianie aplikacji, ponieważ każdy dodatkowy plik jest ładowany osobno. Na ART z Androidem 8.0+ różnica jest minimalna dzięki kompilacji dex2oat do jednego pliku .oat.
\nTak, istnieją projekty, takie jak dexplorer i implementacje JVM kompatybilne z Androidem, które mogą wykonywać bajtkod DEX poza Androidem. Jednak większość plików DEX używa Android API, co czyni je nieprzydatnymi do uruchomienia na zwykłej JVM.
\nPodsumowanie
\nOpracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również