← Назад к вопросам

Какой подход к компиляции применяется в современных версиях Android?

2.0 Middle🔥 121 комментариев
#JVM и память#Производительность и оптимизация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Подход к компиляции в современных версиях Android

В современных версиях Android, начиная с Android 5.0 (Lollipop) и особенно с внедрением Android Runtime (ART), используется комбинированный подход к компиляции, сочетающий AOT (Ahead-of-Time), JIT (Just-in-Time) и, с Android 7.0, гибридную модель с профильно-ориентированной компиляцией. Этот эволюционировавший подход направлен на баланс между производительностью, использованием памяти и временем установки приложений.

Эволюция подходов к компиляции

  1. Dalvik и JIT (до Android 4.4): Изначально в Android использовалась виртуальная машина Dalvik с чистой JIT-компиляцией. Байт-код приложения (DEX-файл) интерпретировался во время выполнения, а "горячие" методы (часто выполняемые) компилировались в нативный код машинно-зависимым компилятором на лету. Это экономило место на диске (не нужно хранить скомпилированный код), но добавляло накладные расходы на компиляцию во время работы и стартовую задержку.

  2. 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, а динамическая, адаптивная и профильно-ориентированная гибридная система. Она минимизирует недостатки каждого из методов в отдельности, обеспечивая лучший баланс между скоростью установки, использованием системных ресурсов и производительностью приложений в долгосрочной перспективе. Для разработчика понимание этой модели важно при анализе производительности, особенно времени холодного старта приложения.