Как JVM выполняет байт-код?

«Как JVM выполняет байт-код?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

JVM использует гибридный подход: интерпретацию и JIT-компиляцию (Just-In-Time).

Основные этапы выполнения:

  1. Загрузка: ClassLoader загружает .class файлы.
  2. Верификация: Проверяется безопасность и корректность байт-кода.
  3. Подготовка: Выделяется память для статических полей и инициализируются значения по умолчанию.
  4. Разрешение: Символические ссылки заменяются на прямые.
  5. Инициализация: Выполняются статические инициализаторы.
  6. Выполнение:
    • Интерпретация: Байт-код выполняется построчно виртуальным процессором JVM (медленно, но без задержек на компиляцию).
    • JIT-компиляция (HotSpot): Часто исполняемые участки кода («горячие пятна») компилируются в оптимизированный машинный код для процессора хоста, что резко ускоряет последующие выполнения.

Пример байт-кода: Исходный метод:

public int add(int a, int b) {
    return a + b;
}

Соответствующий байт-код (упрощённо):

iload_1  // Загрузить первый int-аргумент в стек
iload_2  // Загрузить второй int-аргумент в стек
iadd     // Сложить два верхних значения стека
ireturn  // Вернуть результат со стека

Почему гибридный подход? Интерпретация обеспечивает быстрый старт, а JIT-компиляция — высокую производительность долгоживущих приложений.