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 компилация на горещи методи. Това намалява времето за инсталиране и заетото място.
Паралелно работи фонов профилировчик (background profiler). Той събира статистика за изпълнението: кои методи се извикват най-често, кои клонове на кода се изпълняват, кои класове се зареждат. След натрупване на достатъчно данни (обикновено след 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 (компактиране на heap-а), large object space (отделно съхранение на големи обекти) и concurrent compaction (паралелно компактиране).
Типична пауза на GC в ART е 2–3 ms в сравнение с 5–10 ms в Dalvik. Това стана възможно благодарение на няколко механизма. Първо, ART използва read-barrier вместо stop-the-world за конкурентни фази. Второ, поколенческият събирач обработва само младото поколение обекти в повечето цикли, без да засяга целия heap. Трето, large object space (LOS) се разпределя отделно и не участва в обикновените GC цикли.
// Включване на GC логове за отстраняване на грешки
System.logV("ART", "GC trigger: allocation failed");
// Принудително извикване на GC (не се препоръчва в продукция)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Debug.getRuntimeIStats();
}
Въпреки подобрения GC, изтичането на памет остава актуален проблем. Причина, специфична за ART — зареждане на нативни библиотеки чрез JNI без коректно освобождаване. Ако нативният код разпределя памет чрез malloc, но не извиква free, ART не може да освободи тази памет — тя се намира извън управлявания heap. Инструментът 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 MB (DEX) | +20% (OAT) |
| Паузи на GC | 5–10 ms | 2–3 ms |
| Консумация на енергия | По-висока (JIT загрява CPU) | По-ниска (нативен код) |
Всички приложения, написани за Dalvik, работят на ART без промени. Google гарантира пълна обратна съвместимост на ниво DEX байткод. Изключение — код, използващ Dalvik-specific вътрешно 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 поддържа инструкцията 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 да генерира допълнителни stub-ове, което забавя изпълнението с 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също