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) керує звільненням пам’яті. Інтерпретатор виконує рідко викликаний код без компіляції. Профілювальник відстежує гарячі методи для гібридної компіляції. Кожен модуль може працювати незалежно, що робить ART гнучкою та масштабованою.
Починаючи з Android 7.0 Nougat, ART використовує гібридний підхід до компіляції, що поєднує переваги JIT та AOT. Під час установлення додатка ART більше не виконує повну AOT-компіляцію — натомість додаток запускається в інтерпретованому режимі з JIT-компіляцією гарячих методів. Це скорочує час установлення та обсяг займаного місця.
Паралельно працює фоновий профілювальник. Він збирає статистику виконання: які методи викликаються найчастіше, які гілки коду виконуються, які класи завантажуються. Після накопичення достатньої кількості даних (зазвичай після 2–3 запусків додатка) ART запускає dex2oat в фоні та компілює лише профільовані гарячі методи в нативний код.
ART підтримує кілька режимів компіляції, що керуються через system_server. Режим «speed» компілює всі методи з AOT (максимальна продуктивність, довге установлення). Режим «speed-profile» компілює лише профільовані гарячі методи (баланс швидкості та розміру). Режим «verify» лише перевіряє байт-код без компіляції (мінімальне місце, інтерпретація). За замовчуванням використовується speed-profile — оптимальний для більшості додатків.
| Режим | Компіляція | Час установлення | Продуктивність |
|---|---|---|---|
| speed | Повна AOT | Довго | Максимальна |
| speed-profile | Профільована AOT | Швидко | Висока |
| verify | Без компіляції | Миттєво | Інтерпретація |
| space | Мінімальна AOT | Середнє | Середня |
Профілювальник збирає дані про виконання в спеціальні .prof-файли. Кожен додаток зберігає свій профіль в /data/misc/profiles/. При досягненні порога (зазвичай 1000 вібірок) профілювальник запускає dex2oat для компіляції виявлених гарячих методів. Профілі зберігаються між оновленнями додатка, що прискорює повторну оптимізацію після 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 для конкурентних фаз. По-друге, поколінневий збирач обробляє лише молоде покоління об’єктів у більшості циклів, не зачіпаючи всю купу. По-третє, 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 компілював гарячі методи. На 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 (лямбди, посилання на методи, 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 через механізм десугарингу. Лямбді, посилання на методи та функціональні інтерфейси працюють на всіх пристроях з Android 5.0+. Для Stream API та java.time потрібна бібліотека desugar_jdk_libs.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також