Какой подход к компиляции применяется в современных версиях Android?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Подход к компиляции в современных версиях Android
В современных версиях Android, начиная с Android 5.0 (Lollipop) и особенно с внедрением Android Runtime (ART), используется комбинированный подход к компиляции, сочетающий AOT (Ahead-of-Time), JIT (Just-in-Time) и, с Android 7.0, гибридную модель с профильно-ориентированной компиляцией. Этот эволюционировавший подход направлен на баланс между производительностью, использованием памяти и временем установки приложений.
Эволюция подходов к компиляции
-
Dalvik и JIT (до Android 4.4): Изначально в Android использовалась виртуальная машина Dalvik с чистой JIT-компиляцией. Байт-код приложения (DEX-файл) интерпретировался во время выполнения, а "горячие" методы (часто выполняемые) компилировались в нативный код машинно-зависимым компилятором на лету. Это экономило место на диске (не нужно хранить скомпилированный код), но добавляло накладные расходы на компиляцию во время работы и стартовую задержку.
-
ART и полный AOT (Android 5.0 - 6.0): С введением ART как новой среды выполнения, Android перешёл на исключительно AOT-компиляцию. Во время установки приложения (
dex2oat) весь DEX-байт-код компилировался в нативный код (файлы.oatили.art). Это значительно повышало производительность во время выполнения и время запуска приложения, но увеличивало время установки, занимаемый объём памяти (в 2-3 раза) и требовало больше места на диске.
Современная гибридная модель (Android 7.0+)
Начиная с Android 7.0 (Nougat), была внедрена интеллектуальная гибридная модель компиляции, сочетающая JIT, AOT и профильно-ориентированную компиляцию. Это основная архитектура вплоть до текущих версий (Android 14+). Её работа разделена на несколько этапов:
// Упрощённая иллюстрация жизненного цикла компиляции
fun applicationLifecycle() {
// 1. Установка / Первый запуск
val app = installApp() // DEX-файлы копируются
// -> Интерпретатор + JIT-компиляция "горячих" методов
// 2. Фоновая компиляция
while (deviceIsIdleAndCharging()) {
profileGuidedAOTCompilation() // Использует собранный профиль
}
// 3. Последующие запуски
app.launch() // Загружаются AOT-скомпилированные методы из профиля
}
Ключевые компоненты современного подхода:
-
Интерпретатор: При первом запуске приложения код выполняется интерпретатором. Это позволяет приложению запуститься быстро, без задержек на компиляцию.
-
JIT-компилятор с кэшированием профиля:
* Во время работы приложения **JIT-компилятор** постоянно анализирует выполнение кода, идентифицируя "горячие" методы (те, что вызываются часто).
* Эти методы компилируются в нативный код "на лету" для ускорения текущей сессии.
* **Важнейшее нововведение**: JIT сохраняет **профиль выполнения** (профильные данные) о скомпилированных методах в специальный файл. Этот профиль содержит информацию о том, какие методы действительно важны для производительности, какие классы загружаются вместе (холодный старт) и какие ветки кода чаще исполняются.
- Фоновая AOT-компиляция, управляемая профилем:
* Когда устройство находится в состоянии покоя, подключено к зарядке и, часто, к Wi-Fi, система запускает фоновую задачу `dex2oat`.
* Эта задача **не компилирует весь код приложения**, а использует собранный JIT'ом **профиль** для AOT-компиляции только тех методов и классов, которые критичны для производительности и быстрого запуска.
* Результат (скомпилированный нативный код) сохраняется. При следующих запусках приложения эти ключевые методы будут загружаться уже в скомпилированном виде, что даёт выигрыш в скорости, сравнимый с полным AOT, но при значительно меньшем объёме скомпилированного кода.
- Хранение скомпилированного кода: Скомпилированный код хранится в разделе
data(в папке/data/dalvik-cache/или внутри данных приложения), а не в разделеsystem. Это позволяет каждому пользователю иметь свои оптимизированные версии приложений и даёт возможность системе очистить кэш, не затрагивая установленные APK-файлы.
Преимущества гибридного подхода
- Быстрая установка и обновление: Первая установка происходит почти мгновенно, так как нет этапа долгой AOT-компиляции.
- Оптимальное использование памяти (RAM/ПЗУ): Компилируется только часто используемый код, а не весь APK.
- Высокая производительность в runtime: Критичные методы со временем получают оптимизированный нативный код.
- Адаптивность: Профиль обновляется при изменении паттернов использования приложения, и фоновая компиляция может переоптимизировать код.
- Снижение потребления батареи: Фоновая компиляция происходит только в идеальных условиях.
Дополнительные технологии (Android 8.0+)
- Compact DEX: Формат хранения DEX-файлов, оптимизированный для прямого исполнения из памяти, что уменьшает занимаемый объём RAM.
- Верификация во время выполнения (VDEX): Ускоряет проверку байт-кода при установке.
- Cached app profiles: Система может делиться профилями между пользователями устройства или даже предустанавливать общие профили через Google Play, чтобы новые пользователи сразу получали преимущества оптимизации.
Итог: Современный подход Android к компиляции — это не выбор между AOT или JIT, а динамическая, адаптивная и профильно-ориентированная гибридная система. Она минимизирует недостатки каждого из методов в отдельности, обеспечивая лучший баланс между скоростью установки, использованием системных ресурсов и производительностью приложений в долгосрочной перспективе. Для разработчика понимание этой модели важно при анализе производительности, особенно времени холодного старта приложения.