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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

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