openjdk.ruOpenJDK на русском

JEP 343: Packaging Tool (Incubator)

Инструмент упаковки в статусе Incubator (инкубационный модуль)

ОтветственныйKevin Rushforth
ТипFeature
ОбластьJDK
СтатусClosed / Delivered
Выпуск14
Компонентtools / jpackage
Обсуждениеcore dash libs dash dev at openjdk dot java dot net
ТрудоёмкостьM
ДлительностьM
Связан сJEP 311: Java Packager API & CLI
JEP 392: Packaging Tool
РецензентыAlan Bateman, Alexander Matveev, Alexey Semenyuk, Andy Herrick, Mandy Chung, William Harnois
ОдобренBrian Goetz
Создан2018/04/04 19:22
Обновлён2021/08/28 00:10
Задача8200758

Аннотация

Создать инструмент для упаковки автономных Java-приложений.

Цели

Создать простой инструмент упаковки на основе инструмента JavaFX javapackager, который:

  • Поддерживает нативные форматы пакетов, чтобы установка была привычной для конечных пользователей. К этим форматам относятся msi и exe в Windows, pkg и dmg в macOS, deb и rpm в Linux.

  • Позволяет задавать параметры запуска на этапе упаковки.

  • Может вызываться напрямую из командной строки или программно через API ToolProvider.

Что не является целью

  • Следующие возможности инструмента javapackager поддерживаться не будут:
    • поддержка приложений Java Web Start,
    • возможности, специфичные для JavaFX,
    • использование jdeps для определения необходимых модулей и
    • плагин для Ant.
  • Графического интерфейса у инструмента не будет: интерфейса командной строки (CLI) достаточно.
  • Кросс-компиляция поддерживаться не будет. Например, чтобы создать пакеты для Windows, инструмент нужно запускать в Windows. Инструмент упаковки будет зависеть от инструментов конкретной платформы.
  • Особой поддержки юридических файлов сверх той, что уже есть в файлах JMOD, не будет. Отдельные файлы лицензий объединяться не будут.
  • Поддержки нативной заставки (splash screen) не будет.
  • Механизма автоматического обновления не будет.
  • Инструмент не будет доступен в Solaris.

Мотивация

Многие Java-приложения нужно устанавливать на нативную платформу полноценно, а не просто помещать в class path или module path. Разработчику приложения недостаточно поставить простой JAR-файл: он должен поставить устанавливаемый пакет, подходящий для нативной платформы. Так Java-приложения можно распространять, устанавливать и удалять привычным для пользователей способом. Например, в Windows пользователи ожидают, что смогут установить программу двойным щелчком по пакету, а затем удалить её через панель управления; в macOS пользователи ожидают, что смогут дважды щёлкнуть по DMG-файлу и перетащить приложение в папку Applications.

Инструмент упаковки также может помочь закрыть пробелы, оставшиеся после других технологий, например Java Web Start, удалённого из JDK 11 от Oracle, и pack200, который в JDK 11 получил статус Deprecated for Removal (устаревший, будет удалён) с удалением в одном из будущих выпусков. Разработчики могут с помощью jlink урезать JDK до минимального набора нужных модулей, а затем с помощью инструмента упаковки создать сжатый устанавливаемый образ, который можно развернуть на целевых машинах.

Раньше для этих задач вместе с JDK 8 от Oracle поставлялся инструмент упаковки javapackager. Однако он был удалён из JDK 11 от Oracle вместе с удалением JavaFX.

Описание

Инструмент jpackage упаковывает Java-приложение в пакет для конкретной платформы, который содержит все необходимые зависимости. Приложение может быть представлено набором обычных JAR-файлов или набором модулей. Поддерживаются следующие форматы пакетов для конкретных платформ:

  • Linux: deb и rpm
  • macOS: pkg и dmg
  • Windows: msi и exe

По умолчанию jpackage создаёт пакет в формате, наиболее подходящем для системы, в которой он запущен.

Базовое использование: немодульные приложения

Допустим, у вас есть приложение из JAR-файлов, которые лежат в каталоге lib, и lib/main.jar содержит главный класс. Тогда команда

$ jpackage --name myapp --input lib --main-jar main.jar

упакует приложение в формат, принятый по умолчанию в локальной системе, и оставит полученный файл пакета в текущем каталоге. Если в файле MANIFEST.MF в main.jar нет атрибута Main-Class, главный класс нужно указать явно:

$ jpackage --name myapp --input lib --main-jar main.jar \
  --main-class myapp.Main

Пакет будет называться myapp, хотя имя самого файла пакета будет длиннее и будет заканчиваться типом пакета (например, myapp.exe). В пакет войдёт лаунчер приложения, который тоже будет называться myapp. Чтобы запустить приложение, лаунчер поместит в class path JVM каждый JAR-файл, скопированный из входного каталога.

Если вы хотите создать пакет в формате, отличном от формата по умолчанию, используйте параметр --type. Например, чтобы создать в macOS файл pkg, а не dmg:

$ jpackage --name myapp --input lib --main-jar main.jar --type pkg

Базовое использование: модульные приложения

Если у вас модульное приложение, состоящее из модульных JAR-файлов и/или файлов JMOD в каталоге lib, а главный класс находится в модуле myapp, то команда

$ jpackage --name myapp --module-path lib -m myapp

упакует его. Если модуль myapp не указывает свой главный класс, то, опять же, его нужно указать явно:

$ jpackage --name myapp --module-path lib -m myapp/myapp.Main

(При упаковке модульного JAR-файла или файла JMOD главный класс можно указать параметром --main-class инструментов jar и jmod.)

Метаданные пакета

Инструмент jpackage позволяет задавать для пакета различные метаданные. Параметры, общие для всех платформ:

  • --app-version <version>
  • --copyright <string>
  • --description <string>
  • --license-file <file>
  • --name <string>
  • --vendor <string>

Инструмент использует аргументы этих параметров так, как это принято для данного типа пакета. Параметры метаданных пакета для конкретных платформ описаны ниже.

Ассоциации файлов

Для приложения можно задать одну или несколько ассоциаций с типами файлов с помощью параметра --file-associations, который можно указывать несколько раз. Аргумент этого параметра — файл свойств со значениями одного или нескольких из следующих ключей:

  • extension задаёт расширение файлов, ассоциируемых с приложением,
  • mime-type задаёт MIME-тип файлов, ассоциируемых с приложением,
  • icon задаёт значок внутри образа приложения, используемый для этой ассоциации, и
  • description задаёт краткое описание ассоциации.

Лаунчеры

По умолчанию инструмент jpackage создаёт для приложения простой нативный лаунчер. Лаунчер по умолчанию можно настроить следующими параметрами:

  • --arguments <string> — аргументы командной строки, передаваемые главному классу, если лаунчеру не переданы аргументы командной строки (этот параметр можно указывать несколько раз)
  • --java-options <string> — параметры, передаваемые JVM (этот параметр можно указывать несколько раз)

Если приложению нужны дополнительные лаунчеры, их можно добавить с помощью параметра --add-launcher:

  • --add-launcher <launcher-name>=<file>

Указанный <file> должен быть файлом свойств со значениями одного или нескольких ключей app-version icon arguments java-options main-class main-jar module или win-console. Значения этих ключей будут интерпретироваться как аргументы одноимённых параметров, но применительно к создаваемому лаунчеру, а не к лаунчеру по умолчанию. Параметр --add-launcher можно указывать несколько раз.

Образы приложений

Инструмент jpackage строит образ приложения, который служит входными данными для инструмента упаковки конкретной платформы, вызываемого на последнем шаге. Обычно этот образ — временный артефакт, но иногда его нужно настроить перед упаковкой. Поэтому инструмент jpackage можно запускать в два шага. Сначала создайте исходный образ приложения со специальным типом пакета app-image:

$ jpackage --name myapp --module-path lib -m myapp --type app-image

Будет создан образ приложения в каталоге myapp. Настройте этот образ как нужно, а затем создайте итоговый пакет с помощью параметра --app-image:

$ jpackage --name myapp --app-image myapp

Образы среды выполнения

Образ приложения содержит как файлы, из которых состоит приложение, так и образ среды выполнения JDK, в котором приложение будет работать. По умолчанию инструмент jpackage вызывает инструмент jlink, чтобы создать образ среды выполнения. Содержимое образа зависит от типа приложения:

  • Для немодульного приложения из JAR-файлов образ среды выполнения содержит тот же набор модулей JDK, который обычный лаунчер java предоставляет приложениям из class path в безымянном модуле.

  • Для модульного приложения из модульных JAR-файлов и/или файлов JMOD образ среды выполнения содержит главный модуль приложения и транзитивное замыкание всех его зависимостей. В него войдут не все доступные поставщики сервисов; если вы хотите, чтобы они были связаны, укажите параметр --bind-services инструмента jpackage.

В обоих случаях, если в образ среды выполнения нужно добавить дополнительные модули, можно использовать параметр --add-modules инструмента jpackage. Список модулей в образе среды выполнения находится в файле release образа.

Образы среды выполнения, созданные инструментом jpackage, не содержат отладочных символов, обычных команд JDK, man-страниц и файла src.zip.

Если вы хотите дополнительно настроить образ среды выполнения, можно самостоятельно вызвать jlink и передать полученный образ инструменту jpackage через параметр --runtime-image. Например, если с помощью инструмента jdeps вы выяснили, что вашему немодульному приложению нужны только модули java.base и java.sql, можно значительно уменьшить размер пакета:

$ jlink --add-modules java.base,java.sql --output myjre
$ jpackage --name myapp --input lib --main-jar main.jar --runtime-image myjre

Особенности платформ

В этом разделе описаны особенности инструмента jpackage на разных платформах, в том числе структура образов приложений и параметры для конкретных платформ. Команда jpackage --help выводит сводку по всем параметрам.

Образы приложений, созданные инструментом jpackage, содержат некоторые файлы, не показанные в приведённых ниже структурах; такие файлы следует считать деталями реализации, которые могут измениться.

Linux
myapp/
  bin/              // Application launcher(s)
    myapp
  lib/
    app/
      myapp.cfg     // Configuration info, created by jpackage
      myapp.jar     // JAR files, copied from the --input directory
      mylib.jar
      ...
    runtime/        // JDK runtime image

Каталог установки по умолчанию в Linux — /opt. Его можно переопределить параметром --install-dir.

Параметры для Linux:

  • --linux-package-name <package name> — имя пакета для Linux, по умолчанию совпадает с именем приложения
  • --linux-deb-maintainer <email address> — сопровождающий (maintainer) DEB-пакета
  • --linux-menu-group <menu-group-name> — группа меню, в которую помещается приложение
  • --linux-package-deps <deps> — пакеты или возможности, необходимые приложению
  • --linux-rpm-license-type <type string> — тип лицензии (License: <value> файла RPM .spec)
  • --linux-app-release <release value> — значение Release файла RPM <name>.spec или значение Debian revision управляющего файла DEB
  • --linux-app-category <category value> — значение Group файла RPM <name>.spec или значение Section управляющего файла DEB
  • --linux-shortcut Создаёт ярлык для приложения
macOS
MyApp.app/
  Contents/
    Info.plist
    MacOS/          // Application launcher(s)
      MyApp
    Resources/      // Icons, etc.
    app/
      MyApp.cfg     // Configuration info, created by jpackage
      myapp.jar     // JAR files, copied from the --input directory
      mylib.jar
      ...
    runtime/        // JDK runtime image

Каталог установки по умолчанию в macOS — /Applications. Его можно переопределить с помощью параметра --install-dir.

Параметры, специфичные для macOS:

  • --mac-package-identifier <string> — идентификатор, однозначно определяющий приложение для macOS (по умолчанию имя главного класса; допускаются только буквы, цифры, дефис и точка)
  • --mac-package-name <string> — имя приложения в строке меню (по умолчанию имя приложения; должно быть короче 16 символов и подходить для отображения в строке меню и в окне сведений о приложении Info)
  • --mac-package-signing-prefix <string> — при подписании пакета приложения (bundle) значение, добавляемое в начало идентификаторов всех компонентов, которые нужно подписать, но у которых ещё нет идентификатора bundle
  • --mac-sign — запросить подписание пакета (bundle)
  • --mac-signing-keychain <file> — путь к связке ключей (keychain), в которой ищется идентификатор для подписи (по умолчанию стандартные связки ключей)
  • --mac-signing-key-user-name <team name> — часть идентификатора подписи Apple с названием команды (например, «Developer ID Application: »)
Windows
MyApp/
  MyApp.exe         // Application launcher(s)
  app/
    MyApp.cfg     // Configuration info, created by jpackage
    myapp.jar     // JAR files, copied from the --input directory
    mylib.jar
    ...
  runtime/        // JDK runtime image

Каталог установки по умолчанию в Windows — C:/Program Files/. Его можно переопределить с помощью параметра --install-dir.

Параметры, специфичные для Windows:

  • --win-console — создаёт консольный лаунчер для приложения (следует указывать для приложений, которым требуется взаимодействие через консоль)
  • --win-dir-chooser — добавляет диалог, в котором пользователь может выбрать каталог для установки приложения
  • --win-menu — добавляет приложение в системное меню
  • --win-menu-group <menu-group-name> — группа меню «Пуск», в которую помещается приложение
  • --win-per-user-install — установить приложение для отдельного пользователя
  • --win-shortcut — создать ярлык приложения на рабочем столе
  • --win-upgrade-uuid <string> — UUID, связанный с обновлениями этого пакета

Поставка jpackage

Инструмент jpackage будет поставляться в JDK как Incubator-модуль с именем jdk.incubator.jpackage. Поскольку эта возможность поставляется в Incubator-модуле, стабильность параметров командной строки, структуры приложения и других экспортируемых интерфейсов инструмента jpackage не гарантируется, и они могут быть пересмотрены в будущем выпуске. При запуске из командной строки инструмент будет выводить предупреждение. Модуль jdk.incubator.jpackage не будет разрешаться по умолчанию, а при его разрешении будет выводиться предупреждение.

Инструмент jpackage основан на инструменте javapackager, из которого удалены все возможности, связанные с Java Web Start и JavaFX. Интерфейс командной строки (CLI) соответствует JEP 293 (Guidelines for JDK Command-Line Tool Options). Помимо интерфейса командной строки, jpackage доступен через ToolProvider API (java.util.spi.ToolProvider) под именем "jpackage".

Тестирование

Большую часть тестов можно выполнить автоматизированными скриптами, но нужно учитывать несколько моментов:

  • Для тестирования нативных пакетов может потребоваться установка дополнительных инструментов; такие тесты нужно писать так, чтобы они пропускались в системах, где нужных инструментов нет.

  • Проверка некоторых типов нативных пакетов (например, exe в Windows или dmg в macOS) может потребовать ручного тестирования.

  • Нам нужно убедиться, что нативные пакеты устанавливаются и удаляются чисто, чтобы разработчики могли тестировать в своём локальном окружении, не опасаясь засорить свои системы.

Зависимости

Нативные пакеты будут создаваться с помощью инструментов целевой платформы. Для Windows есть дополнительный инструмент, который разработчикам нужно будет установить, если они хотят создавать нативные пакеты:

  • Для создания пакетов msi или exe требуется Wix — сторонний инструмент

Ведётся работа над улучшением jlink, чтобы в будущей версии JDK он мог создавать нативные лаунчеры. Может потребоваться определённая координация между jlink и jpackage.