Project Valhalla: как десять лет работы наконец входят в JDK 28

Project Valhalla: как десять лет работы наконец входят в JDK 28

15 июня инженер Oracle Лоис Фолтан подтвердила интеграцию JEP 401 в основной репозиторий OpenJDK с целевой версией JDK 28. Project Valhalla, над которым работают уже десять лет, наконец получает первую реальную реализацию. Правда, она придёт в виде preview и по умолчанию отключена, а сам проект едва ли закончится на этом.

Пул-реквест добавляет более 197 тысяч строк кода по 1816 файлам. Само по себе это заслуживает уважения. Но контекст ещё важнее: проблема, которую решает Valhalla, возникла в самых основаниях Java и требовала переосмысления целых слоёв виртуальной машины.

Ключевые факты

  • Project Valhalla интегрируется в JDK 28 (preview, отключена по умолчанию)
  • Pull request добавляет 197 000 строк кода в 1816 файлов
  • Это только первая часть проекта; планируется ещё специализация обобщённых типов (generics)
  • Основной вызов: написание классов с производительностью примитивов и проектировать память плотнее, чем кучей ссылок на объекты
  • Проект переходил через пять прототипов, менял названия трижды, избавился от давних идей (вроде dual projection и Q World)

Ред. Хотелось бы видеть в истории Projects более внимание к неудачам. "Пять прототипов" звучит как хаос, пока не поймёшь, что это честь к проектам, которые знают, когда отступить.

Почему это важно

Вся Java построена на ссылочных типах. Когда вы пишете Point p = new Point(1, 2), переменная p это не сам точка. Это указатель на объект где-то в heap. Для одного объекта это ничего, но на масштабе миллионов элементов каждый доступ к полю требует следования по указателю (pointer indirection), а это убивает локальность в памяти. Современные CPU в два порядка быстрее памяти; весь зазор закрывается кешем. Плотно расположенные данные загружаются в кеш целыми строками (64 байта), разреженные ссылки создают cache miss каждый раз. Value classes позволяют писать читаемый, безопасный код, но с памятью и кешем как примитивы.

Ред. Это не просто оптимизация для пережившихся систем. Это честное признание, что железо выиграло войну и язык должен смириться.

Кому это важно

В первую очередь автором высоконагруженных систем: графики, игровые движки, image processing, базы данных, аналитика, HPC. Десять лет они обходились хаком: вместо класса Color использовали три отдельных байта r, g, b. Работает быстро, но теряется безопасность (легко спутать BGR с RGB и молча испортить изображение). Value classes снимают это противоречие. Для CRUD-приложений изменений практически не будет, но для систем, где каждый байт и каждое выделение памяти считаются, это может быть проорыв.

Ред. Любопытно наблюдать, как язык признаёт, что не все приложения созданы равными, и это нормально.

Как это применить

Сейчас ждёте JDK 28 и экспериментируйте с preview-флагом. Синтаксис простой: вместо public class Point пишете public value class Point. Поля становятся финальными по умолчанию, синхронизация запрещена. На самом деле это перевод на язык современного аппаратного обеспечения: value objects не имеют identity (в смысле synchronized или equals по ссылке). Если вам нужны nullable value types, это придёт в отдельном JEP (Null-Restricted Value Class Types) позже. На данный момент основной проект намеренно упрощён: orthogonal concepts вместо одного сложного.

Ред. Разработчики нарочно разбили problem space на части, чтобы каждая была усваиваемой. Это признак зрелости, не спешки.

Можно ли доверять

Проект велся transparently в течение десяти лет с поддержкой JavaOne, JEP drafts, State of Valhalla documents от Brian Goetz. Но честно, процесс был шумным. Было пять прототипов, три волны переименования (value types > inline classes > primitive classes > value classes), и две вещи прямо отвергнуты (две версии draft JEP). Это может показаться хаосом, но вообще это означает, что бюрократия не убила проект раньше, чем нужно. Тестирование и рецензирование в OpenJDK обычно жёсткое. Preview в JDK 28 это не бета, это говорит: "вот оно, пробуйте, но будьте готовы к breaking changes в следующих версиях".

Ред. Preview это честный контракт: "мы не сломаем вам production, но тесты лучше обновите".

Риски и подводные камни

Главный риск это то, что project Valhalla может упраздниться через несколько версий, как это случилось с другими JEP. Сообщество шутит уже лет пять, что скорее попадёте в скандинавскую Валгаллу, чем в Java-версию. Второй риск это миграция кода: если вы пишете на Java и используете escape analysis как костыль производительности, то когда сможете использовать value classes, вам придётся полностью перепроектировать структуры данных. Третий: это только начало. Полное Valhalla (включая специализацию generics) ещё не скоро. И четвёртый: не забудьте о null. Value classes по умолчанию не могут быть null, но nullable variant еще не готов, поэтому рефакторинг code, который полагается на null, может быть болезненным. Нужны tools поддержка в IDEs и лучше тестовое coverage перед миграцией.

Ред. Десять лет ожидания, и первый шаг это preview. Если уж и есть Валгалла, то разработчики её точно заслужили.

"codes like a class, works like an int"

— Project Valhalla