JEP 275: Modular Java Application Packaging
Модульная упаковка Java-приложений
| Автор | Danno Ferrin |
| Ответственный | Chris Bensen |
| Тип | Feature |
| Область | JDK |
| Статус | Closed / Delivered |
| Выпуск | 9 |
| Компонент | deploy / packager |
| Обсуждение | openjfx dash dev at openjdk dot java dot net |
| Трудоёмкость | M |
| Длительность | M |
| Связан с | JEP 282: jlink: The Java Linker |
| Рецензенты | Alan Bateman, Kevin Rushforth, Mandy Chung |
| Одобрен | Kevin Rushforth |
| Создан | 2015/05/15 19:33 |
| Обновлён | 2017/04/27 21:15 |
| Задача | 8080531 |
Аннотация
Интегрировать в Java Packager возможности проекта Jigsaw, включая поддержку модулей и создание пользовательской среды выполнения.
Мотивация
Java Packager (javapackager) всегда создавал огромные двоичные файлы, когда ему требовалось включить в пакет среду выполнения, из-за размера JRE. Проект Jigsaw разработает инструмент, описанный в JEP 282 jlink: The Java Linker. Он позволяет создавать образы среды выполнения, содержащие подмножество стандартных модулей и модулей JDK, и благодаря этому Java Packager сможет уменьшить размер включаемого образа среды выполнения.
Описание
В основном порядок работы Java Packager останется прежним. Будут добавлены новые инструменты из Jigsaw, и в некоторых случаях они заменят отдельные шаги.
Генерация только приложений для Java 9
Java Packager будет создавать только приложения, использующие среду выполнения JDK 9. Это упростит многие пути выполнения кода и допущения относительно инструментов, которые используются для сборки приложений и сред выполнения Java. Если пользователю нужно создать приложение для Java 8, версия Java Packager для Java 8, поставляемая с JDK 8, продолжит работать. Мы предполагаем, что число автономных приложений, которым нужно одновременно работать на Java 8 и Java 9, будет практически нулевым, поскольку приложение приносит с собой собственную JVM.
Использование jlink для генерации встроенных образов среды выполнения Java и приложений
Сейчас JRE копируется, а ненужные части удаляются из скопированной среды выполнения.
Инструмент компоновки Java, jlink, позволяет сгенерировать образ JRE, содержащий только необходимые модули. Кроме того, jlink может предоставить точки расширения для процесса генерации образа, которыми мы можем воспользоваться для дальнейшей настройки образа, например добавив в обработку jlink удаление исполняемых файлов или сжатие.
Java Packager будет вызывать jlink для создания образа среды выполнения приложения, который будет встроен в образ приложения. Если jlink завершится с ошибкой, Java Packager завершится с соответствующей ошибкой. Ожидается, что упакованные модули будут поставляться с JDK 9.
Инструмент jlink включает механизм плагинов и расширений. При использовании jlink для генерации образа приложения мы интегрируемся с этими механизмами, чтобы результатом процесса jlink был образ приложения в правильной структуре, специфичной для платформы. Полезным побочным эффектом станет то, что генерация образа приложения не будет зависеть от процесса Java Packager.
Аргументы командной строки javapackager, задачи Ant и Java Packager API
У Java Packager появились новые аргументы командной строки, соответствующие синтаксису и значениям параметров остальных инструментов Java, описанным в JEP 261:
--add-modules <module>(,<module>)*
--limit-modules <module>(,<module>)*
--module-path <path>(:<path>)*
-p <path>(:<path>)*
--module <module>/<classname>
-m <module>/<classname>
Чтобы указать аргумент для длинного параметра, можно использовать --<name>=<value> или --<name> <value>.
ПРИМЕЧАНИЕ: --module-path соответствует параметру --module-path инструмента jlink, но с необязательным значением по умолчанию. Подробнее ниже.
Появятся новые задачи ANT, дочерние для <fx:application>, <fx:secondaryLauncher> и новой задачи <fx:runtime>.
Например:
<fx:deploy outdir="${bundles.dir}"
outfile="MinesweeperFX"
nativeBundles="all"
verbose="true">
<fx:runtime strip-native-commands="false"> <-- new
<fx:add-modules value="java.base"/>
<fx:add-modules value="jdk.packager.services,javafx.controls"/>
<fx:limit-modules value="java.sql"/>
<fx:limit-modules value="jdk.packager.services,javafx.controls"/>
<fx:module-path value="${java.home}/../images/jmods"/>
<fx:module-path value="${build.dir}/modules"/>
</fx:runtime>
<fx:application id="MinesweeperFX"
name="MinesweeperFX"
module="fx.minesweeper" <-- new
mainClass="minesweeper.Minesweeper"
version="1.0">
</fx:application>
<fx:secondaryLauncher name="Test2"
module="hello.world" <-- new
mainClass="com.greetings.HelloWorld">
</fx:secondaryLauncher>
</fx:deploy>
<fx:runtime>, <fx:limit-modules>, <fx:add-modules>, <fx:modular-path> — необязательные аргументы. Аргумент module="module name" в <fx:application> используется при упаковке модульного приложения, а если приложение немодульное, он недопустим. Аргументы <fx:limit-modules>, <fx:add-modules>, <fx:modular-path> взаимозаменяемы с --add-mods, --limit-mods и --module-path, используемыми в этом документе. Дополнительные сведения об аргументах модулей см. в разделе «Конфигурации модулей».
В Java Packager API появятся новые методы для модульных параметров.
Удаление нативных команд
По умолчанию Java Packager удалял команды, такие как java.exe, но некоторым разработчикам нужны инструменты командной строки, такие как java.exe. Поэтому появится параметр, позволяющий включать нативные команды за счёт отключения удаления команд:
--strip-native-commands false
Добавление поддержки модулей и путей модулей
Jigsaw вводит понятие «пути модулей» (module path) в дополнение к classpath. Путь модулей состоит из путей к библиотекам, модулям JDK и модулю приложения. Пути, содержащие эти модули, задаются аргументом командной строки:
--module-path <path>(:<path>)*
Его можно указать только один раз, и это путь в формате платформы. Корневые модули и их транзитивные зависимости компонуются в модульный образ среды выполнения (JEP 220).
Разработчик может указать путь к упакованным модулям, чтобы включить в пакет версию среды выполнения Java, отличную от версии по умолчанию. Если разработчик не предоставил упакованные модули JDK, Java Packager по умолчанию использует упакованные модули, поставляемые с той версией JDK, в составе которой поставляется сам Java Packager ($JAVA_HOME/jmods).
Сейчас Java Packager не предоставляет механизма для копирования упакованных модулей в образ среды выполнения приложения вместо компоновки в jimage. Скорее всего, такой сценарий понадобится, если приложение поддерживает плагины и эти модули находятся вне включённого в пакет образа. В этом случае разработчику придётся переопределить --module-path и --add-modules с помощью пользовательских переопределений аргументов JVM.
Конфигурации модулей
Java Packager будет упаковывать Java-приложения двух типов: немодульные JAR и модульные приложения.
Немодульные JAR — это JAR-файлы, не содержащие module-info.class. Для приложений используйте -appClass и -BmainJar=. Разработчики будут использовать Java Packager с теми же аргументами, что и в версиях до JDK 9, то есть с аргументами -srcfiles, -Bclasspath=, -appClass и -BmainJar=. Для обратной совместимости новые модульные аргументы не требуются, и по умолчанию встроенная среда выполнения Java будет состоять из всех распространяемых модулей, поэтому размер включаемой среды выполнения не уменьшится. Чтобы включить сторонние (3rd party) модули, разработчики могут использовать --module-path, --add-modules и --limit-modules.
Например:
javapackager -deploy -v -outdir output -name HelloWorld -Bclasspath=hello.world.jar -native -BsignBundle=false -BappVersion=1.0 -Bmac.dmg.simple=true -srcfiles hello.world.jar -appClass HelloWorld -BmainJar=hello.world.jar
Модульные приложения состоят из JAR, распакованного модуля или упакованного модуля, содержащего module-info.class. Чтобы упаковать модульное приложение, необходимо указать аргументы --module и --module-path. --module нельзя использовать вместе с -appClass и -BmainJar=. --module-path должен содержать путь, включающий главный модуль (модуль, указанный с помощью --module). Другие модули можно добавить в run-time image с помощью --add-modules и --limit-modules. Модули, загружаемые динамически через рефлексию (core reflection) или сервисы, необходимо указать вручную с помощью --add-modules. Главный модуль и модули, указанные в --add-modules, определяют корневые модули. jlink создаст образ среды выполнения с указанными корневыми модулями и их транзитивными зависимостями.
Например:
javapackager -deploy -v -outdir output -name Test -native -BsignBundle=false -BappVersion=1.0 -Bmac.dmg.simple=true --module-path /path/to/jmod --module hello.world/com.greetings.HelloWorld
Эта команда создаст образ среды выполнения, состоящий из главного модуля и всех его транзитивных зависимостей. Другие модули можно добавить с помощью параметра --add-modules.
Модули
Упаковщик будет разделён на два модуля:
jdk.packager
jdk.packager.services
jdk.packager содержит Java Packager, который собирает пакет приложения и установщики. jdk.packager.services — модуль, включаемый в пакет приложения; он предоставляет доступ к сервисам упаковщика во время выполнения, например к пользовательским аргументам JVM.
JNLP
Какие пакеты будут сгенерированы, зависит от входных данных и указанных параметров. Раньше -deploy генерировал все нативные пакеты и файлы .jnlp. Теперь -deploy вместе с -module не будет генерировать файлы .jnlp, поскольку JNLP не поддерживает новые модульные параметры. -native без параметров сгенерирует все доступные нативные пакеты.
Тестирование
Прежде всего, существующие вызовы Java Packager через API, командную строку и Ant, работавшие в JDK 8, должны работать и в JDK 9, поэтому следует запускать существующие тесты упаковщика JDK 8.
Потребуется написать новые тесты для проверки новых флагов, добавленных для поддержки генерации run-time image, указания module-path и взаимодействия с процессом jeeps.
Риски и допущения
Мы предполагаем, что проект будет реализован в основном так, как описано. Если крупные функциональные части, такие как путь модулей и система модулей, будут перенесены в более поздние выпуски, соответствующие части этого JEP также будут отложены.