Android Runtime (ART) — среда выполнения Android-приложений, внедрённая в Android 5.0 Lollipop в качестве замены Dalvik. Главное нововведение — предварительная AOT-компиляция DEX-байт-кода в нативный машинный код непосредственно при установке приложения, что устранило многолетнюю проблему прогрева JIT-компилятора. По данным Google, 2024, ART обеспечивает прирост производительности до 20–30% по сравнению с Dalvik при сохранении полной обратной совместимости с DEX-форматом.
Главное
Android Runtime (ART) — среда выполнения приложений, которая компилирует DEX-байт-код в нативный машинный код до момента запуска. В отличие от Dalvik, использовавшей Just-In-Time компиляцию во время работы, ART выполняет Ahead-Of-Time (AOT) компиляцию при установке APK. Это фундаментальное изменение архитектуры привело к значительному ускорению приложений и снижению энергопотребления.
Впервые ART появилась как экспериментальная опция в Android 4.4 KitKat. Разработчики могли включить её в настройках для разработчиков и тестировать свои приложения. В Android 5.0 Lollipop ART стала средой выполнения по умолчанию, а Dalvik была полностью удалена из платформы. К моменту выхода Android 7.0 Nougat ART получила гибридный режим компиляции.
Решение заменить Dalvik на ART не было внезапным. Работа над новой средой началась в 2012 году, когда Google осознала ограничения JIT-подхода. Основные цели: ускорение запуска приложений, снижение нагрузки на процессор и уменьшение энергопотребления. Разработкой руководила команда Android Runtime Group, ранее работавшая над оптимизациями Dalvik.
ART использует ту же регистровую архитектуру, что и Dalvik, но с полностью переработанным компилятором. Вместо интерпретатора и JIT-компилятора ART включает AOT-компилятор dex2oat, который преобразует DEX-файлы в ELF-бинарники при установке. В результате приложение на ART запускается сразу с нативной производительностью, без фазы прогрева.
ART сохранила ключевые принципы Dalvik: изоляцию приложений через отдельные процессы, регистровую архитектуру и поддержку DEX-формата. Однако внутренняя реализация была полностью переписана. Вместо интерпретатора Dalvik ART включает три исполнительных режима: интерпретатор, JIT-компилятор и AOT-компилятор dex2oat. Выбор режима зависит от стадии жизненного цикла приложения.
Ключевой компонент ART — dex2oat (dalvik executable to optimized android translator). Эта утилита запускается при установке приложения (начиная с Android 7.0 — также при фоновой оптимизации). dex2oat считывает DEX-файлы из APK, оптимизирует байт-код и генерирует OAT-файл — ELF-бинарник с нативным кодом. OAT-файлы хранятся в директории /data/dalvik-cache/.
# Проверка OAT-файлов на устройстве
adb shell ls -la /data/dalvik-cache/arm64/
# Принудительная перекомпиляция приложения
adb shell cmd package compile -m speed com.example.app
Система ART состоит из нескольких взаимосвязанных модулей. Компилятор dex2oat отвечает за генерацию нативного кода. Сборщик мусора (GC) управляет освобождением памяти. Интерпретатор выполняет редко вызываемый код без компиляции. Профилировщик отслеживает hot-методы для гибридной компиляции. Каждый модуль может работать независимо, что делает ART гибкой и масштабируемой.
Начиная с Android 7.0 Nougat, ART использует гибридный подход к компиляции, сочетающий преимущества JIT и AOT. При установке приложения ART больше не выполняет полную AOT-компиляцию — вместо этого приложение запускается в интерпретируемом режиме с JIT-компиляцией hot-методов. Это сокращает время установки и объём занимаемого места.
Параллельно работает фоновый профилировщик (background profiler). Он собирает статистику выполнения: какие методы вызываются чаще всего, какие ветки кода исполняются, какие классы загружаются. После накопления достаточного объёма данных (обычно через 2–3 запуска приложения) ART запускает dex2oat в фоне и компилирует только профилированные hot-методы в нативный код.
ART поддерживает несколько режимов компиляции, управляемых через system_server. Режим "speed" компилирует все методы в AOT (максимальная производительность, долгая установка). Режим "speed-profile" компилирует только профилированные hot-методы (баланс скорости и размера). Режим "verify" только проверяет байт-код без компиляции (минимальное место, интерпретация). По умолчанию используется speed-profile — оптимальный для большинства приложений.
| Режим | Компиляция | Время установки | Производительность |
|---|---|---|---|
| speed | Полная AOT | Долго | Максимальная |
| speed-profile | Профилированная AOT | Быстро | Высокая |
| verify | Без компиляции | Мгновенно | Интерпретация |
| space | Минимальная AOT | Средне | Средняя |
Профилировщик собирает данные о выполнении в специальные .prof-файлы. Каждое приложение хранит свой профиль в /data/misc/profiles/. При достижении порога (обычно 1000 сэмплов) профилировщик запускает dex2oat для компиляции выявленных hot-методов. Профили сохраняются между обновлениями приложения, что ускоряет повторную оптимизацию после OTA-обновлений системы.
Сборка мусора в ART кардинально улучшена по сравнению с Dalvik. Вместо однопоточного Concurrent Mark and Sweep (CMS) ART использует поколенческий сборщик с несколькими оптимизациями: moving collector (уплотнение кучи), large object space (отдельное хранение больших объектов) и concurrent compaction (параллельное уплотнение).
Типичная пауза GC в ART составляет 2–3 мс против 5–10 мс в Dalvik. Это стало возможным благодаря нескольким механизмам. Во-первых, ART использует read-barrier вместо stop-the-world для concurrent-фаз. Во-вторых, поколенческий сборщик обрабатывает только молодое поколение объектов в большинстве циклов, не затрагивая всю кучу. В-третьих, large object space (LOS) выделяется отдельно и не участвует в обычных циклах GC.
// Включение логов GC для отладки
System.logV("ART", "GC trigger: allocation failed");
// Принудительный вызов GC (не рекомендуется в production)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Debug.getRuntimeIStats();
}
Несмотря на улучшенный GC, утечки памяти остаются актуальной проблемой. ART-специфичная причина — загрузка нативных библиотек через JNI без корректного освобождения. Если нативный код выделяет память через malloc, но не вызывает free, ART не может освободить эту память — она находится вне управляемой кучи. Инструмент AddressSanitizer в Android NDK помогает выявлять такие утечки.
ART и Dalvik — две принципиально разные реализации одной задачи: исполнение Android-приложений. Различия затрагивают все уровни: от компиляции до управления памятью. Ниже приведено сравнение по ключевым параметрам производительности и совместимости.
Основное преимущество ART — устранение JIT-прогрева. На Dalvik приложение могло тормозить первые 3–10 секунд, пока JIT компилировал hot-методы. На ART все методы уже скомпилированы в нативный код (или будут скомпилированы в фоне). Это особенно заметно в играх и приложениях с тяжёлым UI: разница в fps может достигать 15–20% в пользу ART.
| Параметр | Dalvik | ART |
|---|---|---|
| Компиляция | JIT (во время работы) | AOT + гибрид (при установке) |
| Время запуска | 3–10 с (прогрев) | Мгновенно |
| Размер APK | ~6–7 МБ (DEX) | +20% (OAT) |
| Паузы GC | 5–10 мс | 2–3 мс |
| Энергопотребление | Выше (JIT греет CPU) | Ниже (нативный код) |
Все приложения, написанные для Dalvik, работают на ART без изменений. Google гарантирует полную обратную совместимость на уровне DEX-байт-кода. Исключение — код, использующий Dalvik-specific internal API через рефлексию: члены классов dalvik.system.DexFile, которые помечены @hide в Android SDK. Такой код следует обновить до использования публичных API.
ART стала первой средой выполнения Android с нативной поддержкой Java 8 фич. Начиная с Android 7.0 ART включает десахаринг — процесс преобразования Java 8 конструкций (лямбды, method references, Stream API) в эквивалентный Java 7 код. Это позволяет использовать современный синтаксис без потери совместимости со старыми устройствами.
Десахаринг выполняется компилятором D8 и работает следующим образом. Исходный код с лямбдой преобразуется в синтетический метод внутри того же класса, а лямбда заменяется на вызов invoke-custom. ART's runtime включает поддержку инструкции invoke-custom, добавленную специально для Java 8. На устройствах с Android 6.0 и ниже лямбды десахарируются в анонимные классы.
// Java 8 лямбда — десахаринг в ART
button.setOnClickListener(v -> handleClick(v));
// После десахаринга (эквивалент на Java 7)
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleClick(v);
}
});
Не все Java 8 фичи поддерживаются десахарингом. java.time API (даты и время) доступен только через desugar_jdk_libs — дополнительную библиотеку, добавляемую в build.gradle. Stream API также требует desugar_jdk_libs. java.util.function и Optional работают без дополнительных зависимостей. Полная поддержка Java 8 доступна на устройствах с Android 8.0 и выше без десахаринга.
Хотя ART обратно совместима, некоторые практики оптимизации улучшают производительность именно на этой среде. Главная рекомендация — минимизировать рефлексию. ART компилирует методы, которые видны на этапе компиляции, в прямой вызов машинного кода. Рефлексия вынуждает ART генерировать дополнительные stubs, что замедляет выполнение на 10–15%.
Начиная с Android 9.0 в ART появилась поддержка App Startup Optimization. Разработчик может пометить классы инициализации в манифесте через <initialization>, и ART предзагрузит их при старте приложения. Это сокращает время запуска на 5–15% для приложений с большим количеством плагинов или библиотек.
<!-- App Startup Optimization в AndroidManifest.xml -->
<application>
<profileable
android:shell="true"
android:enable="true" />
</application>
Для измерения производительности на ART используйте systrace и perfetto. Systrace показывает время компиляции dex2oat, частоту GC и скорость отрисовки кадров. Perfetto даёт более детальную информацию: распределение потоков, время JNI-переходов, загрузку нативных библиотек. Запуск: adb shell perfetto -o /data/misc/perfetto-traces/trace.perfetto -t 10s sched freq idle am wm.
Часто задаваемые вопросы
ART (Android Runtime) — это среда выполнения Android-приложений, которая компилирует код приложения в машинный при установке. Это ускоряет запуск и работу приложений по сравнению со старой средой Dalvik.
ART компилирует код заранее (AOT) при установке приложения, а Dalvik компилировала его по частям во время работы (JIT). Поэтому на ART приложения запускаются быстрее и потребляют меньше энергии.
Выполните adb shell getprop и найдите свойство persist.sys.dalvik.vm.lib.2. Значение "libart.so" означает ART, "libdvm.so" — Dalvik. На всех устройствах с Android 5.0+ среда выполнения — ART.
Незначительно. Само приложение остаётся в формате APK с DEX-файлами. ART создаёт дополнительный OAT-файл в /data/dalvik-cache/, который занимает на 10–20% больше места, чем исходный DEX, но это хранилище не входит в размер APK.
Да, ART поддерживает большинство Java 8 фич через механизм десахаринга. Лямбды, method references и функциональные интерфейсы работают на всех устройствах с Android 5.0+. Для Stream API и java.time требуется библиотека desugar_jdk_libs.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также