В каких случаях лямбда-выражение в Java подвергается деоптимизации JVM?

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

Ответ

Деоптимизация лямбды (или любого метода) в JVM происходит, когда сделанные оптимизирующим компилятором (C2) предположения оказываются неверными. Основные причины:

  1. Изменение целевого типа (Target Type) лямбды — если тип, выводимый компилятором, часто меняется во время выполнения, это может привести к полиморфной инвалидации.

    // Пример: лямбда присваивается разным функциональным интерфейсам
    IntUnaryOperator op1 = x -> x * 2;
    IntBinaryOperator op2 = (x, y) -> x * y;
    // Если один код часто переключается между op1 и op2, может произойти деоптимизация.
  2. Захват изменяемых переменных — лямбда, захватывающая изменяемые локальные переменные (не final или не effectively final), создает более сложный объект, что может помешать инлайнингу.

  3. Мегаморфный вызов сайт — если лямбда реализует интерфейс, для которого существует много различных реализаций в одной точке вызова (обычно >2), JVM откатывается к менее оптимизированной диспетчеризации.

Практический совет: Старайтесь делать лямбды статически предсказуемыми (однотипными, с захватом только effectively final переменных) для стабильной работы JIT-компилятора.