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

JEP 493: Linking Run-Time Images without JMODs

Компоновка образов среды выполнения без файлов JMOD

ОтветственныйSeverin Gehwolf
ТипFeature
ОбластьJDK
СтатусClosed / Delivered
Выпуск24
Компонентtools / jlink
Обсуждениеcore dash libs dash dev at openjdk dot org, jigsaw dash dev at openjdk dot org
ТрудоёмкостьM
ДлительностьM
РецензентыAlan Bateman, Mandy Chung
ОдобренAlan Bateman
Создан2024/06/07 13:36
Обновлён2025/02/20 09:55
Задача8333799

Аннотация

Уменьшить размер JDK примерно на 25 %, дав инструменту jlink возможность создавать пользовательские образы среды выполнения без файлов JMOD, входящих в JDK. Эту возможность нужно включать при сборке JDK. По умолчанию она не будет включена, и некоторые поставщики JDK могут решить её не включать.

Цели

Позволить пользователям компоновать образ среды выполнения из модулей независимо от того, являются ли эти модули отдельными файлами JMOD, модульными JAR-файлами или частью ранее скомпонованного образа среды выполнения.

Мотивация

Размер установленного JDK в файловой системе важен в облачных средах. Там образы контейнеров с установленным JDK автоматически и часто копируются по сети из реестров контейнеров. Уменьшение размера JDK повысило бы эффективность этих операций.

Полный установленный JDK состоит из двух основных частей. Первая — образ среды выполнения, то есть исполняемая среда выполнения Java. Вторая — набор упакованных модулей в формате JMOD, по одному для каждого модуля образа среды выполнения.

Файлы JMOD используются инструментом jlink при создании пользовательских образов среды выполнения. Образ среды выполнения в полном JDK сам является таким образом: он создан из этих файлов JMOD с помощью jlink. Поэтому каждый class-файл, каждая нативная библиотека, каждый конфигурационный файл и любой другой ресурс образа среды выполнения присутствует также в одном из этих файлов JMOD. Пожалуй, это огромная трата места.

На самом деле файлы JMOD в полном JDK занимают около 25 % общего размера JDK. Мы могли бы доработать инструмент jlink, чтобы он извлекал class-файлы, нативные библиотеки, конфигурационные файлы и другие ресурсы из самого образа среды выполнения. Тогда можно было бы отказаться от файлов JMOD и значительно уменьшить размер установленного JDK.

Описание

Новый параметр конфигурации JDK на этапе сборки --enable-linkable-runtime собирает JDK, инструмент jlink которого может создавать образы среды выполнения без файлов JMOD, входящих в JDK. Полученный JDK не содержит этих файлов, то есть каталога jmods в нём нет. Поэтому он примерно на 25 % меньше JDK, собранного с конфигурацией по умолчанию, хотя содержит в точности те же модули.

$ configure [ ... other options ... ] --enable-linkable-runtime
$ make images

Инструмент jlink в любой сборке JDK может принимать как файлы JMOD, так и модульные JAR-файлы. Кроме того, в сборках JDK, где эта возможность включена, jlink может брать модули из образа среды выполнения, частью которого он является. Вывод --help команды jlink показывает, есть ли у него такая возможность:

$ jlink --help
Usage: jlink <options> --module-path <modulepath> --add-modules <module>[,<module>...]
...
Capabilities:
      Linking from run-time image enabled
$

Это означает, что используемый инструмент jlink может компоновать модули JDK из образа среды выполнения, в который он входит. Если бы у него не было такой возможности, он вывел бы Linking from run-time image disabled.

Версия jlink с новой возможностью всегда предпочитает брать модули JDK из файлов JMOD на пути модулей, если они доступны. Модули из образа среды выполнения, частью которого она является, будут использоваться только в том случае, если модуль java.base не найден на пути модулей. Все остальные модули по-прежнему нужно указывать jlink с помощью параметра --module-path.

Для пользователя работа с jlink с новой возможностью выглядит в точности так же, как работа с jlink без неё. Если мы хотим уменьшить размер образа среды выполнения, исключив некоторые модули, мы по-прежнему можем включить только нужные нам модули, но файлы JMOD при этом не нужны. Например, чтобы создать образ среды выполнения, содержащий только модули java.xml и java.base, используется тот же вызов jlink:

$ jlink --add-modules java.xml --output image
$ image/bin/java --list-modules
java.base@24
java.xml@24
$

Вывод jlink в точности такой же, как если бы модули компоновались из файлов JMOD. Полученный образ среды выполнения примерно на 60 % меньше полного образа среды выполнения JDK.

Вызовы для более сложных случаев тоже не меняются. Например, пусть мы хотим создать образ среды выполнения с модулем приложения app, которому нужна библиотека lib. Эти модули упакованы как модульные JAR-файлы в каталоге mlib. Мы, как обычно, указываем их jlink с помощью параметра --module-path:

$ ls mlib
app.jar	lib.jar
$ jlink --module-path mlib --add-modules app --output app
$ app/bin/java --list-modules
app
lib
java.base@24
$

Инструмент jlink копирует class-файлы и ресурсы модулей app и lib из модульных JAR-файлов app.jar и lib.jar. Class-файлы, нативные библиотеки, конфигурационные файлы и другие ресурсы модулей JDK он извлекает из образа среды выполнения JDK.

Параметр --verbose инструмента jlink теперь показывает, откуда взят каждый модуль:

$ ls custom-jmods
foo.jmod
$ jlink --add-modules foo \
        --module-path=custom-jmods \
        --verbose \
        --output foo-image
Linking based on the current run-time image
java.base jrt:/java.base (run-time image)
foo file:///path/to/custom-jmods/foo.jmod

Providers:
  java.base provides java.nio.file.spi.FileSystemProvider used by java.base
$

Здесь модуль java.base извлечён из текущего образа среды выполнения, а модуль foo скомпонован из файла JMOD foo.jmod.

По умолчанию не включено

Конфигурация сборки по умолчанию останется такой же, как сейчас: полученный JDK будет содержать файлы JMOD, и его инструмент jlink не сможет работать без них. Будет ли эта возможность в сборке JDK от выбранного вами поставщика, решает сам поставщик.

В одном из будущих выпусков мы можем предложить включить эту возможность по умолчанию.

Ограничения

У инструмента jlink в JDK, собранном с --enable-linkable-runtime, есть несколько ограничений по сравнению с JDK, собранным с конфигурацией по умолчанию:

  • jlink нельзя использовать для создания образа среды выполнения, который сам содержит инструмент jlink. Инструмент jlink находится в модуле jdk.jlink, поэтому такая команда завершается ошибкой:

    $ jlink --add-modules jdk.jlink --output image
    Error: This JDK does not contain packaged modules and cannot be used \
    to create another run-time image that includes the jdk.jlink module

    В будущем мы можем пересмотреть это ограничение, если оно окажется проблемным.

  • jlink завершается ошибкой, если изменён какой-либо конфигурационный файл, который может редактировать пользователь.

    Каталог conf JDK содержит различные файлы, которые разработчики могут редактировать для настройки JDK. В частности, файл conf/security/java.security настраивает провайдеры безопасности, криптографические алгоритмы и т. д. В сборке по умолчанию jlink копирует редактируемые пользователем конфигурационные файлы модулей JDK из файлов JMOD, входящих в JDK. Без файлов JMOD jlink копирует конфигурационные файлы из образа среды выполнения и завершается ошибкой, если какой-либо из них отличается от исходного файла:

    $ jlink --add-modules java.xml --output image
    Error: [...]/bin/conf/security/java.security has been modified

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

  • Кросс-компоновка невозможна: например, нельзя запустить jlink в Linux/x64, чтобы создать образ среды выполнения для Windows/x64.

  • Компоновка из образа среды выполнения, который сам использует --patch-module, не поддерживается.

  • Компоновка с извлечением модулей из другого образа среды выполнения не поддерживается. Это касается, например, случая, когда этот образ указан в параметре --module-path.

Альтернативы

Поставщик JDK мог бы распространять файлы JMOD для JDK как отдельную загрузку. Некоторые дистрибутивы Linux по сути уже так и делают: они предоставляют один установочный пакет для образа среды выполнения JDK и другой для соответствующих файлов JMOD.

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