DEX: co to jest, struktura i zasada działania bajtkodu

Autor: IT Sectr Opublikowano: 2026-04-15 Czas czytania: 8 min
\n
\n\n
\n

\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

\n
\n\n
\n

Najważniejsze informacje

\n
    \n
  • DEX — format bajtkodu dla Androida, wykonywany na Dalvik lub ART.
  • \n
  • Kompaktowość — DEX zajmuje o 30% mniej miejsca niż standardowy bajtkod Java.
  • \n
  • Multidex — mechanizm do obejścia limitu 65536 metod w jednym pliku DEX.
  • \n
  • ART — Android Runtime, który zastąpił Dalvik, kompiluje DEX do kodu natywnego podczas instalacji.
  • \n
  • D8 — nowoczesny kompilator Java/Kotlin do DEX, który zastąpił DX od 2018 roku.
  • \n
\n
\n\n \n\n
\n

Co to jest DEX i do czego służy

\n\n

DEX (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\n

Od Java do DEX

\n

Kod ź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\n

Cechy architektoniczne

\n

DEX 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.

\n
\n\n
\n

Struktura pliku DEX: sekcje i nagłówek

\n\n

Plik 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 \n \n \n \n \n \n \n \n \n \n \n \n \n \n
SekcjaPrzeznaczenie
headerNagłówek: magic, suma kontrolna, podpis, rozmiary i przesunięcia sekcji
string_idsTabela ciągów: nazwy klas, metod, pól
type_idsTypy: odwołania do identyfikatorów ciągów typów
proto_idsPrototypy metod: typ zwracany i parametry
field_idsPola klas: klasa, typ, nazwa
method_idsMetody: klasa, prototyp, nazwa
class_defsDefinicje klas: flagi, superclass, interfejsy, przesunięcia danych
dataRzeczywiste dane: kod metod, adnotacje, informacje debug
\n\n

Nagłówek DEX

\n

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\n

Pule stałych

\n

string_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.

\n
\n\n
\n

Proces kompilacji Java i Kotlin do DEX

\n\n

Proces 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\n

Etap 1: Kompilacja do .class

\n

javac (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\n

Etap 2: Kompilacja D8

\n

D8 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
kotlin\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
\n\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\n

D8 vs DX

\n

D8 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.

\n
\n\n
\n

Dalvik vs ART: jak zmieniło się wykonywanie DEX

\n\n

Wykonywanie 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\n

Dalvik VM: kompilacja JIT

\n

Dalvik 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\n

ART: kompilacja AOT

\n

ART (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\n

dex2oat: konwersja podczas instalacji

\n

Narzę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.

\n
\n\n
\n

Multidex: przezwyciężenie limitu 64K metod

\n\n

Ograniczenie 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\n

Mechanizm Multidex

\n

Multidex — 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
kotlin\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
\n\n

Problemy Multidex

\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.

\n
\n\n
\n

Optymalizacja DEX: ProGuard, R8 i zaciemnianie

\n\n

Optymalizacja DEX — standardowy etap budowania wersji release aplikacji Android. Narzędzia R8 i ProGuard zmniejszają rozmiar DEX, zaciemniają kod i usuwają nieużywane klasy.

\n\n

R8 vs ProGuard

\n

R8 — 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\n

R8 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\n

Reguły R8

\n

Konfiguracja 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.

\n
\n\n
\n

Dekomplacja DEX: narzędzia i ochrona

\n\n

DEX 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\n

Narzędzia dekompilacji

\n

JADX — 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\n

Metody ochrony

\n

Zaciemnianie 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ę.

\n
\n\n
\n

Często zadawane pytania

\n\n
\n Czym DEX różni się od bajtkodu Java?\n
\n

DEX 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.

\n
\n
\n\n
\n Co to jest smali?\n
\n

Smali — 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.

\n
\n
\n\n
\n Jak sprawdzić liczbę metod w DEX?\n
\n

Gradle 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.

\n
\n
\n\n
\n Czy liczba DEX wpływa na wydajność?\n
\n

Tak, 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.

\n
\n
\n\n
\n Czy można uruchomić DEX bez Androida?\n
\n

Tak, 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.

\n
\n
\n
\n\n
\n

Podsumowanie

\n
    \n
  • DEX — format bajtkodu Android z architekturą rejestrową i kompaktowym przedstawieniem kodu.
  • \n
  • Struktura obejmuje nagłówek, tabele identyfikatorów i sekcję danych z instrukcjami.
  • \n
  • Kompilacja do DEX jest wykonywana przez D8: .class → DEX z optymalizacjami i łączeniem pul stałych.
  • \n
  • ART kompiluje DEX do kodu natywnego podczas instalacji (AOT), przyspieszając uruchamianie aplikacji.
  • \n
  • Multidex — rozwiązanie problemu limitu 65536 metod poprzez podział na kilka plików DEX.
  • \n
  • Optymalizacja — R8 zmniejsza DEX o 20–40%, zaciemnia nazwy i usuwa martwy kod.
  • \n
  • Ochrona — zaciemnianie R8/ProGuard, DexGuard i O-LLVM zapobiegają dekompilacji DEX.
  • \n
\n
\n\n
\n

Opracujemy 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.

Omów projekt

Przeczytaj również