TGViewer
Java: fill the gaps Java: fill the gaps @java_fillthegaps · 12.3K subscribers
Post #306 4.92K
Как устроены лямбды: собираем всё вместе (4/4)

В последней части наконец-то перейдём к лямбда-выражениям.

Что нам уже известно:

🔸 Лямбды не приводят к созданию анонимных классов
🔸 В java 7 появились invokedynamic и MethodHandle API для поддержки динамических языков. Но эти штуки отлично подошли для некоторых java фич, в том числе лямбда-выражений.

Если не читали - прочитайте, тогда этот пост будет понятней.

Итак, разработчик пишет код с лямбда-выражением

stream().filter(x -> x<3)

В байткоде на месте вызова лямбды появляется инструкция

invokedynamic #2, 0

Следуем по указателям из Constant Pool и попадаем в секцию бутстрап-методов. Видим там вызов

LambdaMetafactory.metafactory(…)

Этот фабричный метод возвращает объект CallSite, внутри которого спрятался MethodHandle.

Больше в байткоде нет информации. Понятно, что работа с лямдой - это какое-то перенаправление, а вся магия описана в классе LambdaMetafactory.

Класс лежит в JDK, идём туда и видим:

1️⃣ С помощью ASM библиотечки создаётся внутренний класс. Он реализует интерфейс Predicate и называется как-то так:

class Smth$$Lambda$14/0x0000000800c02460

Класс динамический и существует только в памяти.

2️⃣ Создаётся объект этого класса и привязывается к MethodHandle внутри ConstantCallSite.

3️⃣ Все обращения к лямбде переадресуется этому объекту.

❓Чем это лучше анонимных классов?

✅ Класс создаётся и загружается динамически. Кажется, что это долго и сложно, но на деле получается быстрее, чем загрузка файла с диска
✅ Есть кэширование
✅ Новый класс наравне со всеми участвует в JIT оптимизациях

❓Почему нельзя вынести лямбду в отдельный метод и просто вызывать его?

Чтобы встроить решение в остальной java код. Если в коде пишется

Predicate p = i -> x<3;

То ожидается, что p - это объект. Его можно куда-то передать и вызвать его методы.

Логика вроде "назовём это объектом, но на самом деле это метод" - это слишком большое усложнение. Так не работает. Новые фичи должны вписываться в систему, а не обходить её.

❓Зачем столько переадресаций? Почему из бутстрап метода надо идти в другой класс? Нельзя было сделать встроенную инструкцию?

Текущий код LambdaMetaFactory со временем изменится. Добавится больше кэширования, семантика лямбд расширится в следующих версиях java. Если вся логика описана в JDK, то гораздо легче поддерживать совместимость версий.

Такая вот эпопея. Я весь процесс поняла не с первого раза и даже не со второго. Поэтому решила провести вас маленькими шажками, и описать всё максимально просто.
  • 👍 7
More from @java_fillthegaps
  1. Apr 30, 2026Get Your Hands Dirty on Clean Architecture: отзыв на книгу Когда я подняла тему чистой арх…
  2. Apr 27, 2026​Clean Architecture: отзыв на книгу Наконец-то дочитала книгу Clean Architecture Роберта М…
  3. Mar 4, 2026Как переиспользовать контекст в интеграционных тестах Сегодня расскажу базовый минимум для…
  4. Mar 4, 2026Post #660
  5. Mar 4, 2026Тестовый контекст поднимается 2 минуты. У нас 4 класса с интеграционными тестами, их конфи…
  6. Feb 25, 2026Чистая архитектура. Главы 3-5 Продолжаем спидран по Clean Architecture Роберта Мартина. ⭐️…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →