OpenJDK: Project Panama

54ef833cae1a44189fe0cb4a36b97d17.jpg

Два года назад в OpenJDK был создан новый проект под кодовым названием «Panama». Основным направлением исследований анонсировалось создание нового интерфейса для работы с платформозависимыми библиотеками и данными вне Java heap«а (off-heap). Но цели проекта шире: исследование механизмов взаимодействия JVM и «внешнего» (не-Java) API.

c388cb752fc24ecf8cfa22ab3c55bc1f.jpgВладимир Иванов iwanowww — ведущий инженер Oracle, работает в группе разработки виртуальной Java-машины HotSpot. Специализируется на JIT-компиляции и поддержке альтернативных языков на платформе Java. Владимир пришел в Sun Microsystems (приобретена Oracle в 2010) в 2005 году и с того момента поучаствовал в большом количестве проектов, связанных с Java (HotSpot JVM, RTSJ, JavaFX).

— Большая часть проекта Panama — это работа с native библиотеками из Java кода. Как это можно делать сейчас?

— Работать с native кодом в Java можно было всегда. Native методы были еще в первой версии Java, а стандартный интерфейс JNI появился уже в версии 1.1. Но время идет, платформа развивается, требования меняются и, смотря на JNI сейчас, есть понимание, что можно организовать работу с native библиотеками удобнее и эффективнее.

У JNI есть ряд недостатков, связанных со сложностью в использовании и скоростью работы. Для того, чтобы интегрировать некоторую библиотеку в приложение, необходимо не только написать для нее обертку на С/C++, но и предоставить сборки под все поддерживаемые платформы. Это плохо вписывается в процесс компиляции современных Java приложений и может оказаться существенной преградой при внедрении. Также, в силу своей Java-центричности, каждый вызов через JNI несет определенные накладные расходы, что становится особенно заметно при интенсивной работе даже с небольшими методами. Проект Panama — это, в том числе, попытка создать новую версию JNI, «JNI 2.0», более удобную и производительную. И на это уже есть JEP: JEP 191: «Foreign Function Interface».

— Существует мнение, что JNI был спроектирован настолько сложным, чтобы им было неприятно пользоваться. Как вы к этому относитесь?

— Это что-то из разряда «городских легенд». Хотя в целом, мнение, конечно, ошибочно, в нем есть и доля истины: инвестировать в улучшение JNI не было приоритетом. Считалось, что эффективнее и удобнее писать всё на Java. Существовал интерфейс, который покрывал >90% потребностей пользователей и развивать его не виделось необходимым. Да и с помощью сторонних библиотек можно существенно упростить работу с JNI. Достаточно посмотреть на JNR, который позволяет полноценно работать с native библиотеками без написания и строчки C/C++ кода.

— JNI уже 20 лет, почему проект Panama возник и развивается только сейчас?

— Я бы сказал, что мы дозрели до этого проекта. За эти годы стали очевидны сильные и слабые стороны JNI, да и Java платформа прошла длинный путь в своем развитии. Стало понятно, что не всегда целесообразно разрабатывать приложения полностью на Java, кроме того, намного более востребованной стала работа с данными вне Java heap«а. JNI и NIO уже не удовлетворяют всех потребностей и пользователям приходится работать с sun.misc.Unsafe. Проект Panama призван решить ряд проблем, с которыми они сталкиваются.

Как анонсировал Джон Роуз (John Rose, архитектор JVM из Oracle), курирующий проект: любая полезная библиотека должна быть легко доступна как часть Java экосистемы (вне зависимости от того, написана она на Java или нет).

К примеру, есть пакет линейной алгебры LAPACK, изначально написан на Fortran. Масса ресурсов была инвестирована в оптимизацию, и от переписывания на Java вряд ли можно что-то выиграть. Существенно продуктивнее просто его переиспользовать, как делают, например, C/C++ программисты.

Вообще, первой попыткой «посмотреть вовне» можно считать Project Sumatra, целью которого было исследование перспектив использования GPU для исполнения Java программ. В теории все звучит очень привлекательно: запусти программу на устройстве где доступен GPU, и JVM автоматически начнет его использовать. Но на практике все оказалось не так радужно, и создать эффективный механизм исполнения Java байт-кода на современных GPU так и не получилось. Есть несколько Java библиотек (Aparapi и Rootbeer) для работы с GPU из Java, но они предлагают достаточно низкоуровневый подход, сходный с OpenCL/CUDA.

Panama дает иную перспективу на проблему использования GPU: не обязательно исполнять Java байткод для GPU, достаточно работать с библиотеками, которые знают что делать с GPU. Такой функциональностью обладают, например, некоторые реализации BLAS и пакет линейной алгебры MAGMA.

— Какие задачи сейчас решают программисты с помощью JNI?

— Экосистема Java библиотек богата, но на Java написано далеко не все. Я уже упоминал пакеты линейной алгебры и LAPACK. Единственная возможность задействовать их в Java программе — это JNI. Другим примером является 3D-графика: как работать с OpenGL из Java? Стандартного Java API нет, есть платформенные реализации с нужной функциональностью, но требуется способ интегрироваться с ними из Java. Ответ — опять JNI.

— А какие успешные проекты в данный момент используют JNI?

— В целом, любая более-менее популярная не-Java библиотека имеет версию-обёртку для Java, и конечно же, реализовано это все с помощью JNI. К примеру, в области компьютерного зрения это библиотека OpenCV. Если смотреть на 3D-графику, то это Java Binding for the OpenGL API и Lightweight Java Game Library.

Касательно пакетов линейной алгебры, netlib-java предоставляет доступ к платформенным реализациям BLAS/LAPACK. К слову, присутствует в последних версиях Apache Spark.

Из Java проектов я бы упомянул JRuby, который JNI напрямую не использует, но полагается на JNR для работы с платформозависимым API.

— Кроме интерфейса вызова native библиотек, в проект Panama входит поддержка native структур данных. Вы рассматриваете ее как отдельную функциональность или как фичу, необходимую для вызова native библиотек?

— И то и другое. Основная проблема при работе с native кодом из Java — это обмен данными. Виртуальная машина имеет полную свободу в выборе представления Java объектов, и, зачастую, этот формат никак не согласован с native библиотеками. Приходится либо копировать данные «туда-сюда», либо пытаться работать с одной копией.

JNI предлагает API для доступа к Java heap в native коде, а для работы с off-heap нужно писать код в JNI обертке. Получается очень накладно: как с точки зрения производительности, так и количества требуемого кода.

В Panama ведется работа над новым форматом (Layout Definition Language), который позволяет описывать достаточно сложные структуры данных в компактном и гибком виде. LDL-описания могут быть автоматически извлечены из C/C++ header«ов, а по описанию «на лету» сгенерирован Java код для работы с данными. JVM тоже может использовать эту информацию, например, для поиска указателей на Java объекты при GC. При этом native код сможет работать с этими данными напрямую, без какой-либо дополнительной адаптации.

В комбинации с указателями и явным управлением памятью, это полностью покрывает часть функциональности sun.misc.Unsafe, используемой для off-heap решений.

Но это еще не все. При должной поддержке на стороне JVM, LDL может быть использован для описания структуры Java объектов.

В первую очередь, это позволит контролировать выравнивание и производить padding полей.
В «горячем» коде эффекты false sharing и невыровненные доступы в память серьезно влияют на скорость исполнения. Внутри JDK есть аннотация @Contended, но для пользователя единственный пока способ избежать false sharing«а это вручную «обложить» проблемное поле другими полями, в надежде что JVM сохранит их порядок.

Но, главное, откроет дорогу целому ряду экзотических структур, типа fused-строк (заголовок и массив символов как один объект) или tagged-массивов (каждый элемент массива или примитивное значение, или указатель на объект).

Эта часть проекта перекликается с Valhalla и value-типами в плане создания компактных Java структур с быстрым доступом (как произвольным, так и последовательным) к данным.

— Как думаете, какие из фич проекта будут наиболее востребованы пользователями?

— В Panama есть ряд независимых направлений исследования. Первое — это работа с native кодом и off-heap данными. Как раз сюда входит и новый API на замену JNI. По моим оценкам, эта часть проекта должна быть самой популярной.

Из других направлений я бы отметил API для пакетной обработки данных (Vector API). В современных процессорах есть векторные расширения (SSE и AVX на x86, NEON на ARM), содержащие инструкции для пакетной обработки данных (SIMD инструкции). На текущий момент JVM умеет делать автоматическую векторизацию кода при динамической компиляции, но это не покрывает всех интересных случаев. Идет работа над специализированным API, дающим возможность явно описывать операции пакетной обработки над данными.

Еще одно направление — это обновление Java массивов, также известное как Arrays 2.0. Массивы были в Java с самого начала, и в некоторых аспектах серьезно устарели (например, ограничение на размер в 2Gb). Назрела потребность в более эффективных и гибких механизмов описания и работы с ними.

— Если сравнивать с другими изменениями с JVM и Java, насколько важен проект Panama в данный момент?

— Работа в Panama активно ведется, но пока находится в исследовательской фазе. Нам еще только предстоит определить что и когда интегрировать в Java.

На сегодняшний день ключевым проектом для JDK 9 является модуляризация платформы
(Project Jigsaw).

В контексте же Panama, очень интересно выглядят VarHandle«ы (JEP 193: «Variable Handles»). Они работают как над полями и массивами, так и над off-heap данными, и предоставляют ряд экзотических режимов чтения/записи, которые нельзя описать в терминах стандартной модели памяти Java. Такая поддержка необходима для эффективной реализации неблокирующей синхронизации, и пакет java.util.concurrent уже в JDK 9 полностью мигрировал с sun.misc.Unsafe на VarHandle«ы. Новые примитивы, предложенные в Panama, должны хорошо вписаться в парадигму доступа через VarHandle«ы, унифицировав доступ к on-heap и off-heap данным.

— А в последующих версиях?

— Еще в активной разработке находится Project Valhalla. Проект Panama менее на слуху, но, на мой взгляд, не менее важен для Java платформы в долгосрочной перспективе.

Про FFI и работу с off-heap разговоры шли довольно давно, но в последнее время появился живой интерес и к Vector API. На конференции JVM Language Summit в этом году был забавный момент: при обсуждении Panama коллеги из Facebook настойчиво интересовались когда стоит ждать появления Vector API в Java, и говорили что им он был очень нужен еще года 3 назад. Очень жаль, что они так долго молчали. Надо было сразу поднимать тему, благо на JVMLS они приходят каждый год. В то время поддержка явной векторизации особого интереса не привлекала.

— Ожидаете ли вы, что некоторые проекты, написанные на Java, будут переписаны с использованием нового API?

— Конечно же JNI останется, но для людей, которые сейчас используют JNI, новый API будет гораздо привлекательнее. Судя по нашему опыту, при наличии нового интерфейса необходимости в JNI быть уже не должно.

Мы активно экспериментируем с текущим прототипом и довольны результатами: для извлечения информации из C/C++ header’ов используется Clang, и уже сейчас вся «обвязка» создается новым инструментарием из Panama. Просто, удобно, экономит массу времени при миграции.

— То есть проект Panama будет востребован внутри Java платформы?

— Разумеется, вызов native кода активно используется и внутри платформы, так что с появлением более удобного и эффективного механизма, на него будем постепенно переходить в JDK, но Panama не позиционируется как внутренний. Его цель — создание нового механизма работы с native кодом и с off-heap данными для Java платформы, а это подразумевает появление нового public API.

— То есть JNI останется в языке как legacy фреймворк?

— От JNI никто избавляться пока не собирается. Обратная совместимость крайне важна для Java и поддержка будет продолжена. Возможно, в перспективе JNI будет помечен «на удаление» (как deprecated), но на текущий момент таких планов нет.

Хотел бы также отметить, что от работы над проектом Panama, скорее всего, выиграет и JNI. Для эффективной работы c native кодом требуется серьезная поддержка на стороне JVM. Так что переписывание JNI с использованием новых примитивов JVM может дать существенный прирост производительности.

А что еще интересного станет доступно в JDK 9?

— Из проектов, которые не на слуху, я бы выделил интерфейс JVMCI (JEP 243: «Java-Level JVM Compiler Interface»). С его помощью можно будет подключать сторонний динамический компилятор к JVM, и первым пользователем этого API является Graal, разрабатываемый в Oracle Labs. Это новый JIT-компилятор, полностью написанный на Java.

— То есть можно будет заменить стандартный JIT-компилятор на Graal?

— Да, Graal может быть использован или как компилятор «последнего уровня», генерирующий оптимизированный код (замена серверного компилятора С2 в Hotspot), или как единственный JIT-компилятор в виртуальной машине. Это доступно и сейчас, но необходима специальная сборка JVM.

Вообще, эксперименты с «Java on Java» реализациями шли давно. Был проект Maxine VM — виртуальной машины, полностью (!) написанной на Java. Наибольших успехов удалось достичь в области динамических компиляторов. Ведь Graal начался с попытки переписать клиентский компилятор из HotSpot на Java. В Maxine он даже поначалу назывался С1X. Наконец пришло время внедрять наработки в платформу.

Мне, как JVM инженеру, тренд на переписывание виртуальной машины на Java крайне импонирует. С одной стороны, получаем реализацию на современной платформе, под которую существует удобный инструментарий, высокоуровневые языковые конструкции, обширная стандартная библиотека с отличной поддержкой многопоточного программирования. Немаловажно и то, что эту платформу мы полностью контролируем, так что имеем возможность расширять ее в нужную нам сторону и своими силами решать возникающие проблемы. С другой — добавляем в Java инструменты для решения низкоуровневых задач. И проект Panama будет играть в этом одну из ключевых ролей.


Если вы любите «кишочки» JVM так же, как мы, то кроме доклада Владимира «Native код, Off-heap данные и Java» рекомендуем вам посмотреть следующие доклады Joker 2016:
  • From Java to Assembly: Down the Rabbit Hole
  • Жизненный цикл JIT кода
  • Java на Эльбрусе
  • HotSpot Internals: Safepoints, NullPointers and StackOverflows

Комментарии (0)

© Habrahabr.ru