Dalvik: что это, виртуальная машина и как работает

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

Виртуальная машина Dalvik — ключевой компонент операционной системы Android, отвечавший за исполнение приложений вплоть до версии 4.4 KitKat. Разработанная Дэном Борнштейном регистровая VM пришла на смену концепции стандартной JVM и позволила оптимизировать запуск приложений на мобильных устройствах с ограниченным объёмом оперативной памяти. По данным Google, 2024, Dalvik обеспечивала совместимость приложений через JIT-компиляцию, преобразуя DEX-байт-код в машинные инструкции непосредственно во время выполнения.

Главное

  • Dalvik — виртуальная машина с регистровой архитектурой, оптимизированная для Android.
  • В отличие от JVM, Dalvik исполняет DEX-байт-код, специально сжатый для мобильных устройств.
  • JIT-компиляция преобразует часть DEX-кода в машинный прямо во время работы приложения.
  • Начиная с Android 5.0 Dalvik заменена на ART с предварительной AOT-компиляцией.
  • Понимание Dalvik необходимо для поддержки старых версий Android и анализа обратной совместимости.

Что такое Dalvik?

Dalvik — виртуальная машина с регистровой архитектурой, созданная специально для платформы Android. Разработка началась в 2005 году компанией Дэна Борнштейна, а в 2007 году проект был приобретён Google. Первая коммерческая версия Dalvik появилась вместе с релизом Android 1.0 в 2008 году.

В отличие от стандартной Java Virtual Machine (JVM), Dalvik не исполняет Java-байт-код. Компилятор Java преобразует исходный код в class-файлы, а затем утилита dx переводит их в формат Dalvik Executable (DEX). Этот формат компактнее class-файлов: одно приложение размером 10 МБ в class-формате занимает примерно 6–7 МБ в DEX.

История создания

Дэн Борнштейн написал Dalvik как проект для операционных систем с ограниченными ресурсами. Название взято от исландской деревни Дальвик. Google выбрала Dalvik вместо JVM из-за лицензионных ограничений и необходимости глубокой оптимизации под мобильные процессоры с ARM-архитектурой. Система быстро завоевала популярность: к 2012 году на Dalvik работало более 500 миллионов Android-устройств.

Роль в экосистеме Android

Каждое Android-приложение запускается в отдельном процессе с собственным экземпляром Dalvik VM. Это обеспечивает изоляцию данных и защиту от вредоносного кода на уровне операционной системы. Такой подход сочетает преимущества виртуализации с песочницей Linux — зловред в одном приложении не может повлиять на соседние процессы.

Архитектура Dalvik: регистровая машина и DEX

Регистровая архитектура Dalvik принципиально отличается от стековой архитектуры JVM. Вместо операций с вершиной стека Dalvik оперирует регистрами — виртуальными ячейками внутри VM. Каждая инструкция содержит адреса регистров-операндов, что сокращает количество инструкций на одну операцию.

Стековая машина JVM использует инструкции типа push, pop и add — для сложения двух чисел требуется три инструкции. Dalvik решает ту же задачу одной инструкцией add-int с тремя регистрами. По данным Android Open Source Project, регистровая архитектура DEX сокращает объём байт-кода в среднем на 30% по сравнению со стековым class-форматом.

Формат DEX

DEX-файл (Dalvik Executable) содержит сжатое представление всех классов приложения. Заголовок файла включает контрольную сумму, размеры секций и смещения. Основные секции — это пулы строк, типов, прототипов методов, полей и сам байт-код. В одном DEX-файле может храниться до 65536 методов (ограничение снято введением multi-dex в Android 5.0).

Для преобразования class-файлов в DEX используется утилита dx, входящая в состав Android SDK Build Tools. Пример команды: dx --dex --output=classes.dex myapp.jar. Современные проекты используют D8 — преемник dx с улучшенной оптимизацией и поддержкой Java 8+ фич.

bash
# Преобразование JAR в DEX с помощью dx
dx --dex --output=classes.dex myapp.jar

# Современная версия через D8
d8 --lib android.jar --output dex/ myapp.jar

Zygote: предзагрузка фреймворка

Процесс Zygote — важнейший элемент архитектуры Dalvik. При запуске системы Zygote загружает все классы Android SDK, открывает общие библиотеки и создаёт пул preload-ресурсов. Когда пользователь открывает приложение, система копирует процесс Zygote (fork), создавая новый экземпляр Dalvik VM с уже готовым фреймворком. Это сокращает время запуска приложения с ~2–3 секунд до 300–500 миллисекунд.

JIT-компиляция в Dalvik

JIT (Just-In-Time) — технология компиляции байт-кода в машинные инструкции непосредственно во время выполнения приложения. В Dalvik JIT-компилятор анализирует выполняемый DEX-код, выявляет часто используемые (hot) методы и компилирует их в нативный код для CPU.

Выбор JIT вместо полной Ahead-Of-Time (AOT) компиляции в ранних версиях Android был осознанным. Мобильные устройства имели ограниченный объём флеш-памяти (4–16 ГБ) — предварительная компиляция всех приложений заняла бы значительное место. Кроме того, ROM-память в ранних устройствах работала медленнее, чем оперативная, и чтение заранее скомпилированного кода могло снизить производительность.

Процесс JIT-компиляции

Когда приложение запускается, Dalvik начинает интерпретировать DEX-байт-код. Специальный профилировщик отслеживает, какие методы вызываются чаще всего. После превышения порога (обычно ~200 вызовов) JIT-компилятор преобразует метод в машинный код и кэширует его в оперативной памяти. Последующие вызовы используют уже скомпилированную версию без повторной компиляции.

java
// Пример hot-метода, который JIT скомпилирует
public class Calculator {
    public int sumArray(int[] arr) {
        int total = 0;
        for (int i = 0; i < arr.length; i++) {
            total += arr[i];
        }
        return total;
    }
}

Производительность JIT

По данным Google I/O 2013, внедрение JIT в Android 2.2 Froyo ускорило выполнение приложений в среднем в 2–5 раз по сравнению с чистой интерпретацией. Однако JIT добавляет задержку при первом запуске: приложению требуется от 3 до 10 секунд на прогрев и компиляцию hot-методов. После прогрева производительность стабилизируется на уровне, близком к нативному коду.

Dalvik vs JVM: ключевые отличия

Dalvik отличается от JVM по нескольким фундаментальным параметрам. Первое — архитектура: JVM стековая, Dalvik регистровая. Второе — формат байт-кода: JVM использует class-файлы, Dalvik — DEX. Третье — управление памятью: Dalvik оптимизирована под ограниченный объём RAM мобильных устройств.

Оба подхода имеют сильные стороны. Стековая JVM требует меньше места на хранение инструкций — каждая инструкция короче, так как операнды неявно берутся со стека. Регистровая Dalvik исполняет меньше инструкций на одну операцию, что экономит процессорное время и снижает энергопотребление. Для мобильных устройств с батарейным питанием это критично.

ПараметрDalvikJVM
АрхитектураРегистроваяСтековая
Байт-кодDEXclass
КомпиляцияJIT (Android 2.2+)JIT / AOT
ОптимизацияНизкое энергопотреблениеВысокая совместимость
ИзоляцияЧерез Linux-процессыЧерез ClassLoader

Лицензионные аспекты

Выбор Dalvik вместо JVM также был обусловлен лицензированием. Oracle владеет правами на Java SE и JVM, и Google стремилась избежать лицензионных отчислений. Создание собственной VM с альтернативным форматом байт-кода позволило Android развиваться независимо от Oracle. Этот спор вылился в многолетний судебный процесс Oracle vs Google (2010–2021), завершившийся в пользу Google.

Формат DEX и утилита dx

DEX (Dalvik Executable) — бинарный формат, содержащий скомпилированный код Android-приложения. Каждый DEX-файл начинается с заголовка (header), за которым следуют секции: строковые константы (string_ids), типы (type_ids), прототипы методов (proto_ids), поля (field_ids), методы (method_ids), определения классов (class_defs) и область данных (data).

Утилита dx преобразует Java class-файлы в один или несколько DEX-файлов. Алгоритм работы включает дедупликацию констант — одинаковые строки или типы сохраняются один раз и ссылаются по индексу. Это существенно сокращает итоговый размер. В современных проектах dx заменена на D8 (появилась в Android Studio 3.1), которая работает в 2–3 раза быстрее и поддерживает Java 8 десахаринг.

java
// Пример декомпилированного DEX-байт-кода через dexdump
// Исходный код: return a + b;
@Ldalvik/annotation/Code;
    registers: 3
    add-int v0, v1, v2
    return v0

Multi-dex: преодоление лимита 65536

Ограничение DEX-формата в 65536 методов (лимит 16-битного индекса) стало серьёзной проблемой для крупных приложений. Решение появилось в Android 5.0: поддержка multi-dex позволяет приложению содержать несколько DEX-файлов. Основной classes.dex содержит точки входа, а дополнительные classes2.dex, classes3.dex и так далее — остальной код. Конфигурация multi-dex включается в build.gradle строкой multiDexEnabled true.

Управление памятью и сборка мусора

Сборка мусора в Dalvik реализована как поколенческий (generational) сборщик с маркировкой и очисткой (mark-and-sweep). Память делится на две основные области: Heap (куча) для объектов и Stack (стек) для примитивов и ссылок. При заполнении Heap Dalvik приостанавливает все потоки (STW — Stop-The-World), маркирует достижимые объекты и освобождает недостижимые.

До Android 2.2 Dalvik использовала однопоточный сборщик с длительностью пауз до 100–200 мс. В Android 2.3 Gingerbread появился concurrent-сборщик, сокративший типичные паузы до 5–10 мс. А в Android 4.0 Ice Cream Sandwich добавился сборщик с частичной (incremental) очисткой — Concurrent Mark and Sweep (CMS).

Утечки памяти

Типичная проблема Dalvik-приложений — утечки памяти через статические ссылки на Activity. Если статическое поле хранит ссылку на Context или View, сборщик мусора не может освободить Activity даже после закрытия экрана. Инструменты вроде Eclipse MAT и LeakCanary помогают обнаруживать такие утечки: они анализируют дамп Heap и показывают цепочки ссылок, удерживающих объект.

java
// Пример утечки памяти через статическую ссылку
public class Utils {
    private static Context context;

    public static void init(Context ctx) {
        context = ctx; // Удерживает Activity после finish()
    }
}

Ограничения Dalvik и переход на ART

Несмотря на успех, Dalvik имела ряд недостатков. JIT-компиляция требовала времени на прогрев — первые секунды работы приложения были медленнее. Кроме того, JIT потреблял энергию процессора при компиляции, что сокращало время автономной работы. С ростом производительности мобильных устройств и увеличением объёма встроенной памяти необходимость в JIT снизилась.

В Android 4.4 KitKat Google представила ART (Android Runtime) в качестве экспериментальной замены Dalvik. Начиная с Android 5.0 Lollipop ART стала единственной средой выполнения. Основное отличие — AOT-компиляция: вместо компиляции во время работы все приложения компилируются в машинный код при установке. Это устранило задержки прогрева и улучшило энергоэффективность.

Обратная совместимость

Переход с Dalvik на ART был прозрачным для разработчиков: обе среды исполняют один и тот же DEX-байт-код. Приложения, собранные для Dalvik, работают на ART без перекомпиляции — system_server компилирует их в нативный код при установке. Исключение — код, использующий рефлексию для доступа к внутренним членам Dalvik VM: такой код мог сломаться на ART из-за изменения внутренней архитектуры.

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

Что такое Dalvik простыми словами?

Dalvik — это программа-посредник, которая запускает Android-приложения на телефоне. Она берёт код приложения и превращает его в команды, понятные процессору, делая это прямо во время работы пользователя.

Чем Dalvik отличается от JVM?

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

Почему Google заменила Dalvik на ART?

ART обеспечивает более высокую производительность за счёт предварительной AOT-компиляции — приложение компилируется один раз при установке, а не каждый раз при запуске. Это ускоряет работу и экономит заряд батареи по сравнению с JIT-подходом Dalvik.

Работают ли старые приложения на ART?

Да, ART полностью обратно совместима с DEX-байт-кодом Dalvik. При установке ART компилирует старые DEX-файлы в нативный код. Исключение составляют приложения, использующие рефлексию для доступа к внутренним механизмам Dalvik.

Что такое DEX-файл?

DEX (Dalvik Executable) — формат исполняемого файла, содержащего сжатый байт-код Android-приложения. В одном APK может быть несколько DEX-файлов (multi-dex), если приложение содержит более 65536 методов.

Итоги

  • Dalvik VM — регистровая виртуальная машина, созданная для Android и использовавшаяся до версии 4.4 KitKat.
  • Формат DEX обеспечивает компактное хранение байт-кода — на 30% меньше class-файлов JVM.
  • JIT-компиляция в Dalvik ускоряла выполнение приложений в 2–5 раз по сравнению с чистой интерпретацией.
  • Процесс Zygote предзагружает фреймворк Android, сокращая запуск приложений до 300–500 мс.
  • Ограничение 65536 методов в одном DEX-файле решается через multi-dex начиная с Android 5.0.
  • Сборка мусора в Dalvik прошла путь от однопоточного STW до Concurrent Mark and Sweep.
  • Переход на ART в Android 5.0 устранил задержки прогрева JIT и улучшил энергоэффективность.

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

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

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

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