JIT: суть, Just-In-Time компиляция и как работает

Автор: IT Sectr Опубликовано: 2026-04-16 Время чтения: 9 мин

JIT (Just-In-Time) — технология динамической компиляции, преобразующая байт-код или промежуточное представление программы в машинные инструкции непосредственно во время выполнения. В Android JIT-компилятор впервые появился в версии 2.2 Froyo в составе виртуальной машины Dalvik и ускорил выполнение приложений в 2–5 раз. По данным Google, 2024, современный JIT в ART сочетает интерпретацию с профилированной компиляцией hot-методов.

Главное

  • JIT — Just-In-Time компиляция: преобразование кода в машинный прямо во время работы программы.
  • В Dalvik JIT компилировал hot-методы после преодоления порога вызовов (~200 раз).
  • JIT сокращает время установки и занимает меньше места, чем полная AOT-компиляция.
  • Главный недостаток — задержка прогрева: первые секунды приложение работает медленнее.
  • В современной ART JIT используется в гибридном режиме с фоновой AOT-оптимизацией.

Что такое JIT-компиляция?

Just-In-Time (JIT) — метод компиляции, при котором исходный код или байт-код преобразуется в машинные инструкции не заранее (как при AOT), а в момент первого вызова соответствующего участка программы. Термин "Just-In-Time" означает, что компиляция происходит "как раз вовремя" — непосредственно перед исполнением.

Концепция JIT существует с 1960-х годов, но широкое распространение получила с появлением Java Virtual Machine в 1995 году. JIT позволяет сочетать переносимость байт-кода (пишем один раз — запускаем везде) с производительностью, близкой к нативному коду. В Java HotSpot VM JIT-компилятор анализирует выполняемый код и компилирует только наиболее критичные участки, экономя время и память.

Принцип работы

JIT-компилятор получает на вход байт-код, интерпретирует его и параллельно собирает статистику. Когда некоторый участок кода (метод, цикл) вызывается достаточно часто, JIT принимает решение о компиляции. Скомпилированный машинный код сохраняется в кэше — при повторных вызовах используется уже готовая версия. Это обеспечивает ускорение без необходимости компилировать всю программу целиком.

java
// Пример: метод станет hot после многократного вызова
public class HotMethod {
    private int compute(int n) {
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += i * i;
        }
        return sum;
    }
}

// Вызов 500 раз в цикле — JIT скомпилирует compute
for (int t = 0; t < 500; t++) {
    hot.compute(1000);
}

JIT в Android: Dalvik и ART

В Android JIT-компиляция прошла три фазы эволюции. Первая фаза — Dalvik без JIT (Android 1.0–2.1): чистая интерпретация DEX-байт-кода. Вторая фаза — Dalvik с JIT (Android 2.2–4.4): появление JIT-компилятора, ускорившего приложения в 2–5 раз. Третья фаза — ART с гибридным JIT (Android 7.0+): возвращение JIT в новом качестве.

JIT в Dalvik был реализован как trace-based компилятор. Он анализировал не отдельные методы, а цепочки инструкций (traces), которые часто исполняются последовательно. Это позволяло компилировать целые пути выполнения, включая несколько методов. Такой подход был эффективен для мобильных процессоров с небольшим кэшем инструкций, так как скомпилированный trace укладывался в L1-кэш.

JIT в современной ART

Начиная с Android 7.0 Nougat, ART использует method-based JIT — компилирует отдельные методы на основе профилей выполнения. Этот JIT работает значительно быстрее Dalvik JIT: типичное время компиляции одного метода — 0.5–1 мс против 3–5 мс в Dalvik. Скомпилированный код хранится в отдельной области памяти (JIT code cache), а не в куче приложения, что снижает фрагментацию.

ПараметрDalvik JITART JIT
ТипTrace-basedMethod-based
Скорость компиляции3–5 мс/метод0.5–1 мс/метод
Порог компиляции~200 вызововДинамический
Кэш кодаВ куче приложенияJIT code cache
ПрофилированиеВнутреннееВнешние .prof-файлы

Обнаружение hot-методов и пороги компиляции

Центральный механизм JIT — детекция hot-методов. Каждый вызов метода увеличивает внутренний счётчик. Когда счётчик пересекает порог, метод помечается как "горячий" и отправляется на компиляцию. В Dalvik порог был жёстко задан (~200 вызовов). В ART счётчики настраиваются динамически в зависимости от доступных ресурсов устройства.

Процесс компиляции включает несколько фаз. Первая — анализ байт-кода: JIT изучает поток инструкций и строит граф потока данных (data-flow graph). Вторая — оптимизация: инлайнинг небольших методов, удаление мёртвого кода, свёртка констант. Третья — генерация кода: преобразование оптимизированного графа в машинные инструкции для конкретной архитектуры CPU (ARM, ARM64, x86).

java
// Демонстрация инлайнинга — JIT подставит тело метода
public int inlineExample() {
    return square(5);
}

private int square(int x) {
    return x * x;
} // JIT заменит вызов на return 5 * 5;

OSR — On-Stack Replacement

Особая техника JIT — On-Stack Replacement (OSR). Если метод содержит долгий цикл, который не завершается сотни итераций, JIT может скомпилировать цикл "на лету" и заменить интерпретируемую версию на скомпилированную прямо во время исполнения. OSR особенно эффективен для вычислительных задач: рендеринг, обработка изображений, криптография.

JIT vs AOT: сравнительный анализ

JIT и AOT — два подхода к компиляции с противоположными компромиссами. JIT жертвует скоростью первого запуска ради компактности дистрибутива и адаптивности. AOT жертвует временем установки и объёмом диска ради максимальной производительности с первой секунды. Ни один из подходов не является абсолютно лучшим — выбор зависит от сценария.

Ключевое преимущество JIT — адаптивная оптимизация. JIT может использовать профильную информацию, недоступную AOT: точные типы объектов, реальную частоту вызовов, фактические ветвления. Это позволяет применять агрессивные оптимизации, невозможные при статической компиляции. Например, JIT может виртуализировать вызовы методов (devirtualize), если на практике встречается только один тип получателя.

КритерийJITAOT
Время установкиМгновенноЗависит от размера
Первый запускМедленнее (прогрев)Быстро
Объём на дискеМинимальный+15–30%
АдаптивностьВысокаяНизкая
Потребление CPUПики при компиляцииСтабильное

Когда выбирать JIT

JIT-компиляция предпочтительна, когда важна быстрота развёртывания и экономия дискового пространства. В контексте мобильной разработки JIT идеален для приложений, которые обновляются часто (A/B тестирование, hotfix). Также JIT удобен на стадии разработки, когда код пересобирается десятки раз в день — каждая секунда экономии на компиляции ускоряет цикл обратной связи.

Преимущества JIT-компиляции

JIT предоставляет разработчикам ряд практических преимуществ. Первое — малый размер APK. При JIT-подходе в APK упаковывается только байт-код (DEX), который занимает на 20–30% меньше места, чем скомпилированный нативный код. Для пользователей с ограниченным объёмом встроенной памяти это значимое преимущество.

Второе преимущество — адаптация к устройству. JIT компилирует код с учётом реальной архитектуры CPU, объёма RAM и текущей нагрузки. Например, на устройстве с 2 ГБ ОЗУ JIT может компилировать менее агрессивно, экономя память, а на флагмане с 12 ГБ — применить все возможные оптимизации. AOT-компиляция, напротив, фиксирует решение на момент установки.

Платформенная независимость

Байт-код остаётся платформенно-независимым, что упрощает распространение приложений. Один APK работает на ARM, ARM64 и x86 устройствах, а JIT обеспечивает генерацию нативного кода для каждой архитектуры. Для AOT-подхода потребовалось бы либо включать несколько вариантов нативного кода в APK (увеличение размера), либо компилировать отдельную версию для каждой архитектуры.

Недостатки и ограничения JIT

Главный недостаток JIT — задержка прогрева (warm-up delay). Пользователь видит торможения в первые секунды работы приложения, пока JIT компилирует hot-методы. В играх это проявляется как "заикания" (stuttering) в начальных уровнях. В приложениях с анимациями — подёргивания первых переходов между экранами.

Второй недостаток — энергопотребление. Процесс компиляции интенсивно нагружает CPU, увеличивая энергопотребление на 10–20% в период прогрева. На устройствах с батарейным питанием это сокращает время автономной работы. Особенно заметно в сценариях с частыми перезапусками приложений (многозадачность с ограниченной памятью, когда система выгружает и перезагружает процессы).

Фрагментация кэша

Ещё одна проблема — фрагментация JIT-кэша. Скомпилированный код хранится в непрерывной области памяти. При загрузке новых классов и компиляции дополнительных методов кэш фрагментируется, что увеличивает накладные расходы на управление памятью. В Dalvik эта проблема решалась периодической очисткой кэша; в ART JIT-кэш выделяется отдельно от кучи и использует собственную стратегию дефрагментации.

Гибридный режим: лучшее из двух миров

Современный подход в ART — гибридная компиляция, объединяющая сильные стороны JIT и AOT. При установке приложения компиляция не выполняется — только проверка байт-кода (verify). Это обеспечивает быструю установку и минимальное занятое место. Первые запуски работают в режиме интерпретации с JIT-компиляцией hot-методов — пользователь получает приемлемую производительность без длительного ожидания.

Параллельно работает фоновый профилировщик, собирающий данные о реальном использовании. Через 2–3 полноценных запуска приложения профиль достигает достаточной полноты, и система запускает dex2oat для компиляции hot-методов в нативный код. Эта операция выполняется в фоне, когда устройство не нагружено (зарядка, экран выключен). После завершения фоновой AOT приложение получает производительность, аналогичную полной AOT-компиляции.

bash
# Принудительный запуск фоновой компиляции
adb shell cmd package compile -m speed-profile -f com.example.app

# Просмотр статуса компиляции
adb shell cmd package dump-profiles com.example.app

Результаты гибридного подхода

По данным Google I/O 2017, гибридная компиляция сократила время установки приложений на 30–50% по сравнению с чистой AOT. Объём занимаемого места на системном разделе уменьшился на 20–30%. При этом производительность после фоновой компиляции соответствует уровню полной AOT. Единственный сценарий, где гибрид уступает AOT, — первый запуск сразу после установки: приложение работает в JIT-режиме и может быть медленнее на 10–15%.

Часто задаваемые вопросы

Что такое JIT-компиляция простыми словами?

JIT — это способ ускорения программы, при котором код переводится в машинный язык не заранее, а по частям во время работы. Самые частые участки компилируются и кэшируются, а редкие остаются в исходном виде.

Чем JIT отличается от AOT?

JIT компилирует код во время выполнения, что экономит место и ускоряет установку. AOT компилирует весь код заранее — приложение запускается быстрее, но требует больше места на диске и времени на установку.

Почему JIT был удалён из Android?

JIT не удалён, а эволюционировал. В Android 5.0 Dalvik с JIT заменили на ART с чистой AOT. В Android 7.0 JIT вернулся в ART как часть гибридной системы, где он работает совместно с фоновой AOT-компиляцией для оптимальной производительности.

Как JIT влияет на энергопотребление?

JIT увеличивает энергопотребление на 10–20% в период прогрева из-за нагрузки на CPU. После завершения компиляции hot-методов энергопотребление возвращается к нормальному уровню. Гибридный режим ART минимизирует эти пики за счёт фоновой компиляции.

Виден ли JIT-прогрев пользователю?

Да, в сценариях с интенсивными вычислениями. Пользователь может заметить подтормаживания в первые секунды работы приложения или в начале игры. В современных версиях Android (8.0+) гибридный режим сводит этот эффект к минимуму благодаря профилированной компиляции.

Итоги

  • JIT (Just-In-Time) — динамическая компиляция, преобразующая байт-код в машинные инструкции во время выполнения.
  • В Android JIT прошёл эволюцию: trace-based в Dalvik → полная AOT → гибрид JIT+AOT в современном ART.
  • Hot-методы обнаруживаются через счётчики вызовов и компилируются при превышении порога (~200 вызовов).
  • OSR (On-Stack Replacement) позволяет компилировать долгие циклы на лету без прерывания выполнения.
  • Главные плюсы JIT: малый размер APK, быстрая установка и адаптация к устройству.
  • Главные минусы: задержка прогрева, пиковое энергопотребление и фрагментация кэша.
  • Гибридный режим ART (Android 7.0+) на 30–50% сокращает время установки при сохранении высокой производительности.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также