Статьи

Как Java 9 и Project Jigsaw могут сломать ваш код

Java 9 вырисовывается на горизонте, и он будет поставляться с завершенным Jigsaw проекта . Я не обращал на это особого внимания, пока не узнал из недавнего обсуждения в списке рассылки OpenJFX, что он может сломать существующий код. Это очень необычно для Java, поэтому это пробудило во мне интерес.

Я прочитал JEP проекта и некоторые соответствующие статьи и пришел к выводу, что да, это нарушит существующий код. Это будет зависеть от вашего проекта, зависит ли это от вас, но это может быть и может быть больно.

обзор

После краткого введения в тему проекта Jigsaw я опишу потенциально серьезные изменения.

Я составил этот список изменений из доступных документов. Конечно, нет никакой гарантии, что я поймал все, и, поскольку я не знаком с некоторыми понятиями, я мог ошибиться в некоторых фактах. Пусть покупатель будет бдителен.

Если вы обнаружите ошибку или считаете, что что-то можно сделать более ясным или более точным, оставьте комментарий, и я с удовольствием добавлю ваш вклад.

Проект Пазл

Я мог бы написать более подробное описание проекта Jigsaw в какой-то момент, но сейчас я буду ленив и просто процитирую:

Основными целями этого проекта являются:

  • Сделать платформу Java SE и JDK более легко масштабируемыми до небольших вычислительных устройств;
  • Повышение безопасности и ремонтопригодности реализаций платформы Java SE в целом и JDK в частности;
  • Включить улучшенную производительность приложений; и
  • Разработчикам проще создавать и поддерживать библиотеки и большие приложения для платформ Java SE и EE.

Для достижения этих целей мы предлагаем разработать и внедрить стандартную модульную систему для платформы Java SE и применить эту систему к самой платформе и к JDK. Модульная система должна быть достаточно мощной, чтобы модулировать JDK и другие большие базы унаследованного кода, и при этом быть доступной для всех разработчиков.

Сайт Jigsaw Project – 11 февраля 2015 г.

Если вы хотите узнать больше о проекте, проверьте его сайт и особенно список целей и требований (текущая версия – черновик 3 от июля 2014 года).

Здесь главное забрать модульную систему. Начиная с версии 9, код Java может быть (и будет JRE / JDK) организован в модули вместо файлов JAR.

Код взлома

Это звучит как внутренний рефакторинг, так почему он нарушает существующий код? Ну, это не обязательно делает это, и совместимость является даже одним из центральных требований проекта (как обычно для Java):

Приложение, которое использует только стандартные API Java SE и, возможно, также специфичные для JDK API, должно работать так же […], как и сегодня.

Проект Jigsaw: цели и требования – ПРОЕКТ 3

Важной частью является квалификация «только стандартные API». Существует множество способов создания приложений, которые для некоторых важных деталей полагаются на неопределенные или устаревшие свойства, такие как нестандартные API, недокументированные структуры папок и внутренняя организация файлов JAR.

Итак, давайте посмотрим на потенциально переломные изменения. Для получения более подробной информации, обязательно проверьте сайт проекта, особенно JEP 220 , который содержит более точное описание большинства из следующего.

Внутренние API становятся недоступными

С файлами JAR любой публичный класс виден в любом месте JVM. Это серьезно ограничивает способность JDK-реализаций сохранять внутренние API закрытыми. Вместо этого многие из них доступны, и их часто используют по разным причинам (например, для повышения производительности или обхода [прежних] ошибок во время выполнения Java; FAQ по Java объясняют, почему это может быть плохой идеей ).

Это меняется с модулями. Каждый модуль сможет явно объявить, какие типы доступны как часть его API. JDK будет использовать эту функцию для правильной инкапсуляции всех внутренних API, которые, следовательно, станут недоступными.

Это может оказаться самым большим источником несовместимости с Java 9. Он, безусловно, наименее тонкий, поскольку он вызывает ошибки компиляции.

Чтобы подготовиться к Java 9, вы можете проверить свой код на зависимости от внутренних API. Все, что вы найдете, должно быть заменено тем или иным способом. Некоторые обходные пути могут стать ненужными. Другие классы могут найти свой путь в публичный API. Чтобы выяснить, так ли это, вам придется исследовать и, возможно, обратиться к списку рассылки OpenJDK за интересующей вас функциональностью.

Внутренние API

Так что же такое внутренние API? Определенно все, что живет на sun.* -Пакет. Я не могу подтвердить, является ли все в com.sun.* приватным – конечно, некоторые части есть, но, возможно, не все из них?

Обновление (5 мая 2015 г.): это выяснилось в комментарии Стюарта Маркса :

К сожалению, com.sun представляет собой смесь внутренних и общедоступных («экспортируемых») API. Аннотация @ jdk.Exported отличает последний от внутренних API. Также обратите внимание, что com.sun.* Являются только частью JDK Oracle (ранее Sun) и не являются частью Java SE.

Поэтому, если начинается с com.sun.* , Он не будет существовать ни в одном JDK, com.sun.* от Oracle. И если он принадлежит одному из этих пакетов и не @jdk.Exported , он будет недоступен с Java 9 и далее.

Два примера, которые могут оказаться особенно проблематичными, это sun.misc.Unsafe и все в com.sun.javafx.* . По-видимому, первый используется во многих проектах для критически важного кода и кода производительности. Исходя из личного опыта, я могу сказать, что последний является критически важным компонентом для правильной сборки элементов управления JavaFX (например, все ControlsFX зависит от этих пакетов). Также необходимо обойти ряд ошибок.

Оба этих особых случая рассматриваются для превращения в общедоступный API (см. Unsafe и JavaFX – хотя некоторые люди предпочли бы, чтобы Unsafe погиб в пожаре ).

Поддержка инструментов

К счастью, вам не нужно находить эти зависимости вручную. Начиная с Java 8 JDK содержит jdeps инструмента анализа зависимостей Java ( введение с некоторыми внутренними пакетами , официальную документацию для windows и unix ), который может перечислять все пакеты, от которых зависит проект.

Если вы запустите его с параметром -jdkinternals , он выведет все внутренние API, которые использует ваш проект – именно те, с которыми вам придется иметь дело до того, как Java 9 развернется.

Обновление (15 мая 2015 г.): JDeps еще не распознает все пакеты, которые будут недоступны в Java 9. Это влияет, по крайней мере, на те пакеты, которые принадлежат JavaFX, как это видно в JDK-8077349 . Я не смог найти другие проблемы, связанные с отсутствующей функциональностью (используя этот поиск ).

Обновление (11 мая 2015 г.): я создал плагин Maven, который использует JDeps для обнаружения проблемных зависимостей и прерывает сборку, если обнаружит их. Смотрите пост релиза для деталей.

Слияние JDK и JRE

Основной целью Project Jigsaw является модульность платформы Java, позволяющая гибко создавать образы времени выполнения. Таким образом, JDK и JRE теряют свой отличительный характер и становятся всего лишь двумя возможными точками в спектре комбинаций модулей.

Это подразумевает, что оба артефакта будут иметь одинаковую структуру. Это включает в себя структуру папок и любой код, который опирается на нее (например, используя тот факт, что папка JDK содержит подпапку jre ) перестанет работать правильно.

Внутренние JAR-файлы становятся недоступными

Внутренние файлы JAR, такие как lib / rt.jar и lib / tools.jar , больше не будут доступны. Их содержимое будет храниться в специфичных для реализации файлах с преднамеренно неопределенным и, возможно, изменяющимся форматом.

Код, который предполагает наличие этих файлов, перестанет работать правильно. Это также может привести к некоторым временным проблемам в IDE или подобных инструментах, поскольку они в значительной степени зависят от этих файлов.

Новая схема URL для содержимого изображений во время выполнения

Некоторые API возвращают URL-адреса файлам классов и ресурсов во время выполнения (например, ClassLoader.getSystemResource ). До Java 9 это URL-адреса jar, и они имеют следующую форму:

1
jar:file:<path-to-jar>!<path-to-file-in-jar>

Project Jigsaw будет использовать модули в качестве контейнера для файлов кода, и отдельные JAR-файлы больше не будут доступны. Для этого требуется новый формат, поэтому такие API вместо этого будут возвращать URL-адреса jrt :

1
jrt:/<module-name>/<path-to-file-in-module>

Код, который использует экземпляры, возвращаемые такими API для доступа к файлу (например, с URL.getContent ), будет продолжать работать как сегодня. Но если это зависит от структуры URL-адресов jar (например, путем их создания вручную или их анализа), произойдет сбой.

Удаление одобренного механизма отмены стандартов

Некоторые части Java API считаются автономными технологиями и создаются вне процесса сообщества Java (например, JAXB ). Может быть желательно обновить их независимо от JDK или использовать альтернативные реализации. Механизм одобрения утвержденных стандартов позволяет устанавливать альтернативные версии этих стандартов в JDK.

Этот механизм устарел в Java 8 и будет удален в Java 9. Его заменой являются обновляемые модули .

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

Снятие механизма выдвижения

Благодаря механизму расширения пользовательские API могут быть доступны для всех приложений, запущенных в JDK, без указания их имени в пути к классам.

Этот механизм устарел в Java 8 и будет удален в Java 9. Некоторые функции, которые полезны сами по себе, будут сохранены.

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

Подготовка к Java 9

Вместе эти изменения создают риск для перехода любого крупного проекта на Java 9. Одним из способов оценки и уменьшения этого может быть «всплеск обновлений»: использование jdeps для определения зависимостей от внутренних API. После исправления этих проблем потратьте некоторое время на сборку и запуск своего проекта с помощью одной из ранних сборок доступа Java 9 . Тщательно протестируйте соответствующие части системы, чтобы получить представление о возможных проблемах.

Собранная таким образом информация может быть возвращена в проект, например, путем размещения ее в списке рассылки Jigsaw-Dev . Процитируем (почти) последние слова JEP 220:

Невозможно определить полное влияние этих изменений в аннотации. Поэтому мы должны полагаться на обширное внутреннее и, особенно, внешнее тестирование. […] Если некоторые из этих изменений окажутся непреодолимыми препятствиями для разработчиков, развертывателей или конечных пользователей, тогда мы рассмотрим способы смягчения их воздействия.

Reflection & Lookout

Мы видели, что Project Jigsaw будет модульным во время выполнения Java. Внутренние API (пакеты sun.* И, возможно, com.sun.* ) Будут недоступны, а внутренняя структура JRE / JDK изменится, включая папки и JAR-файлы. После того, как они устарели в Java 8, одобренный механизм переопределения стандартов и механизм расширения будут удалены в Java 9.

Если вы хотите помочь своим друзьям и подписчикам подготовиться к Java 9, обязательно поделитесь этим постом.

Пока что мы сосредоточились на проблемных аспектах проекта Jigsaw. Но это не должно отвлекать от захватывающего и, я думаю, очень позитивного характера запланированных изменений. После прочтения документов, я впечатлен масштабами и возможностями этого следующего выпуска Java. Хотя он, вероятно, не столь новаторский для отдельных разработчиков, как Java 8, он тем более важен для всех, кто занимается сборкой и развертыванием, особенно для крупных монолитных проектов.

Таким образом, я обязательно напишу о Project Jigsaw снова – и затем с акцентом на хорошие стороны. Оставайтесь с нами, если вы хотите прочитать об этом.

Ссылка: Как Java 9 и Project Jigsaw могут сломать ваш код от нашего партнера JCG Николая Парлога в блоге CodeFx .