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