DEX: что это, структура и принцип работы байт-кода

Автор: IT Sectr Опубликовано: 2026-04-15 Время чтения: 8 мин

DEX (Dalvik Executable) — это формат байт-кода, в который компилируется исходный код Android-приложений на Java и Kotlin. Файлы DEX исполняются виртуальной машиной Dalvik (до Android 4.4) или Android Runtime (ART, начиная с Android 5.0). По данным Android Open Source Project, 2026, формат DEX обеспечивает в среднем 30% более компактное представление кода по сравнению со стандартным Java-байткодом JVM.

Главное

  • DEX — формат байт-кода для Android, исполняемый на Dalvik или ART.
  • Компактность — DEX занимает на 30% меньше места, чем standard Java bytecode.
  • Multidex — механизм для обхода лимита в 65536 методов в одном DEX-файле.
  • ART — Android Runtime, заменивший Dalvik, компилирует DEX в нативный код при установке.
  • D8 — современный компилятор Java/Kotlin в DEX, заменивший DX с 2018 года.

Что такое DEX и зачем он нужен

DEX (Dalvik Executable) — это формат байт-кода, разработанный специально для мобильных устройств Android. В отличие от стандартного Java-байт-кода (.class файлы), DEX оптимизирован для ограниченных ресурсов: меньше памяти, меньший размер и более быстрая загрузка классов.

От Java к DEX

Исходный код на Java или Kotlin компилируется javac/kotlinc в стандартные .class файлы (Java bytecode). Затем инструмент d8 (или ранее dx) конвертирует .class в один или несколько DEX-файлов. Эта конвертация не простая переупаковка — d8 выполняет оптимизации: объединяет константные пулы, перезаписывает инструкции в регистровую архитектуру и удаляет дублирующиеся данные.

Архитектурные особенности

DEX использует регистровую архитектуру (в отличие от стековой JVM). Каждый метод имеет фиксированное число регистров (до 65536). Инструкции DEX короче — в среднем 2 байта против 1–4 байт в JVM. Это даёт более компактный код: типичное приложение уменьшается с 10–15 МБ .class до 4–6 МБ .dex.

Структура DEX-файла: секции и заголовок

Файл DEX имеет строго определённую бинарную структуру. Каждый файл начинается с заголовка и содержит несколько секций, которые ссылаются друг на друга через смещения.

СекцияНазначение
headerЗаголовок: magic, контрольная сумма, подпись, размеры и смещения секций
string_idsТаблица строк: имена классов, методов, полей
type_idsТипы: ссылки на строковые идентификаторы типов
proto_idsПрототипы методов: возвращаемый тип и параметры
field_idsПоля классов: класс, тип, имя
method_idsМетоды: класс, прототип, имя
class_defsОпределения классов: флаги, superclass, interfaces, смещения данных
dataФактические данные: код методов, аннотации, debug info

Заголовок DEX

Магическое число DEX — `dex\n035\0` (версия 035). Другие версии: 036, 037, 038 (для Android 8.0+). Заголовок размером 0x70 байт содержит контрольную сумму SHA-1 и смещения всех секций. Валидация заголовка — первый шаг при загрузке DEX виртуальной машиной.

Пулы констант

string_ids, type_ids, proto_ids, field_ids, method_ids — это индексированные таблицы. Вместо хранения полных имён в коде метода используется 4-байтовый индекс. Это ключевая оптимизация: если класс упоминается 100 раз, его имя хранится один раз в string_ids. dex2oat при компиляции ART дополнительно оптимизирует эти таблицы.

Процесс компиляции Java и Kotlin в DEX

Процесс превращения исходного кода в DEX состоит из нескольких этапов. Современная цепочка использует компилятор D8, который пришёл на смену DX в 2018 году с Android Gradle Plugin 3.2.

Этап 1: Компиляция в .class

javac (для Java) или kotlinc (для Kotlin) компилируют исходный код в .class файлы. Каждый класс — отдельный .class файл в Java-байткоде. На этом этапе выполняется проверка типов, генерация bridge-методов и встраивание констант.

Этап 2: D8 компиляция

D8 принимает все .class файлы и преобразует их в DEX-байт-код. D8 выполняет несколько оптимизаций: удаляет неиспользуемые аргументы методов, объединяет константные пулы из разных .class в один глобальный пул DEX, конвертирует стековые инструкции JVM в регистровые инструкции Dalvik.

kotlin
// Исходный код Kotlin
data class User(
    val name: String,
    val email: String
)

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

После компиляции D8 этот код превращается в компактные инструкции DEX: const-string для загрузки строки, iget-object для доступа к полю объекта, invoke-virtual для вызова StringBuilder.append.

D8 vs DX

D8 работает быстрее DX в 2–3 раза, генерирует более компактный DEX (на 5–10%) и лучше оптимизирует Kotlin-специфичные конструкции (inline функции, lambda). DX объявлен deprecated с 2018 года и удалён из Android Gradle Plugin 8.0.

Dalvik vs ART: как изменилось исполнение DEX

Исполнение DEX-кода в Android прошло два этапа: оригинальная виртуальная машина Dalvik (Android 2.2–4.4) и Android Runtime ART (Android 5.0+). Разница в подходе к компиляции кардинальная.

Dalvik VM: JIT-компиляция

Dalvik использовала Just-In-Time (JIT) компиляцию: DEX-байт-код интерпретировался, а часто вызываемые методы компилировались в нативный код на лету. Плюс — быстрая установка. Минус — более медленный запуск и постоянные затраты CPU на JIT.

ART: AOT-компиляция

ART (Android Runtime) компилирует DEX в нативный код при установке приложения через dex2oat. Это Ahead-Of-Time (AOT) подход: установка дольше, но запуск быстрее и потребление энергии меньше. С Android 7.0 ART использует гибридный подход — AOT + JIT + Profile Guided Optimization.

dex2oat: конвертация при установке

Инструмент dex2oat запускается при установке или обновлении приложения. Он компилирует DEX в ELF-файл с нативным кодом под архитектуру устройства. Результат — файлы .oat и .art в директории /data/dalvik-cache/. Google постоянно улучшает dex2oat: на Android 14 добавлена оптимизация для foldable-устройств.

Multidex: преодоление лимита 64K методов

Ограничение в 65536 методов на один DEX-файл — legacy от архитектуры Dalvik. Поле method_ids в заголовке DEX занимает 4 байта, что даёт максимум 2^16 = 65536 уникальных ссылок. Современные приложения с Google Play Services, Firebase и другими SDK легко превышают этот лимит.

Механизм Multidex

Multidex — это механизм разделения кода на несколько DEX-файлов. Главный classes.dex содержит точки входа (Application class, основные Activity), остальные — classes2.dex, classes3.dex и так далее. При запуске классы из дополнительных DEX загружаются через DexClassLoader.

kotlin
// build.gradle.kts — включение multidex
android {
    defaultConfig {
        multiDexEnabled = true
    }
}

// Application class с поддержкой multidex
class MyApp : Application() {
    override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
}

Проблемы Multidex

Загрузка дополнительных DEX на этапе старта приложения может вызывать ANR (Application Not Responding) на устройствах с Android до 5.0. Рекомендация — использовать multidex только при необходимости и минимизировать зависимости, чтобы не превышать лимит.

Оптимизация DEX: ProGuard, R8 и обфускация

Оптимизация DEX — стандартный этап сборки релизного Android-приложения. Инструменты R8 и ProGuard уменьшают размер DEX, обфусцируют код и удаляют неиспользуемые классы.

R8 vs ProGuard

R8 — преемник ProGuard, встроенный в Android Gradle Plugin с 2019 года. R8 выполняет минификацию, обфускацию и оптимизацию за один проход, тогда как ProGuard требовал двух этапов: ProGuard → D8. ProGuard поддерживается до сих пор, но Google рекомендует R8 для новых проектов.

R8 удаляет неиспользуемые классы, методы и поля, переименовывает их в короткие имена (a, b, c), встраивает inline-функции и выбрасывает dead-код. Результат — DEX уменьшается на 20–40% без потери функциональности.

Правила R8

Конфигурация R8 задаётся в файле proguard-rules.pro. Разработчик может указать, какие классы нельзя переименовывать (например, для рефлексии или сериализации Gson). Firebase и другие SDK поставляют собственные правила в своих зависимостях.

Декомпиляция DEX: инструменты и защита

DEX можно декомпилировать обратно в Java-код. Это ключевой вопрос безопасности Android-приложений: без обфускации код восстанавливается до уровня, близкого к исходному.

Инструменты декомпиляции

JADX — самый популярный декомпилятор DEX в Java. Он восстанавливает имена классов, методы, поля и большую часть логики. apktool декомпилирует DEX в smali-код (ассемблер Dalvik) — низкоуровневое представление, близкое к исходным инструкциям. Bytecode Viewer объединяет несколько декомпиляторов в одном интерфейсе.

Методы защиты

Обфускация R8/ProGuard — первая линия защиты: имена классов и методов становятся нечитаемыми. DexGuard — коммерческий инструмент с дополнительными методами: шифрование строк, проверка целостности, анти-tamper. Obfuscation на уровне Control Flow (O-LLVM) изменяет структуру кода, сохраняя его функциональность, но делая анализ намного сложнее.

Часто задаваемые вопросы

Чем DEX отличается от Java-байт-кода?

DEX использует регистровую архитектуру вместо стековой JVM, имеет более компактный формат (на 30% меньше), объединяет все .class в один файл с единым пулом констант и использует 16-битные индексы вместо 8-битных.

Что такое smali?

Smali — это ассемблер DEX-байт-кода. Каждая инструкция DEX имеет текстовое представление в формате smali. Инструмент baksmali конвертирует DEX в smali (дизассемблирование), а smali собирает smali обратно в DEX.

Как проверить количество методов в DEX?

Gradle task countMethods или плагин dex-method-counts показывают количество методов в каждом DEX-файле. Команда adb shell с dumpsys также отображает статистику загруженных DEX для установленных приложений.

Влияет ли количество DEX на производительность?

Да, на устройствах до Android 8.0 многократный DEX замедляет запуск приложения, так как каждый дополнительный файл загружается отдельно. На ART с Android 8.0+ разница минимальна благодаря компиляции dex2oat в единый .oat файл.

Можно ли запустить DEX без Android?

Да, существуют проекты, такие как dexplorer и Android-совместимые JVM-реализации, которые могут исполнять DEX-байт-код вне Android. Однако большинство DEX-файлов используют Android API, что делает их непригодными для запуска на обычной JVM.

Итоги

  • DEX — формат байт-кода Android с регистровой архитектурой и компактным представлением кода.
  • Структура включает заголовок, таблицы идентификаторов и секцию данных с инструкциями.
  • Компиляция в DEX выполняется через D8: .class → DEX с оптимизациями и объединением пулов констант.
  • ART компилирует DEX в нативный код при установке (AOT), ускоряя запуск приложения.
  • Multidex — решение проблемы лимита 65536 методов через разделение на несколько DEX-файлов.
  • Оптимизация — R8 уменьшает DEX на 20–40%, обфусцирует имена и удаляет мёртвый код.
  • Защита — обфускация R8/ProGuard, DexGuard и O-LLVM предотвращают декомпиляцию DEX.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также