- PVSM.RU - https://www.pvsm.ru -

Уменьшение размера дистрибутива в Java 9

Через четыре месяца планируется выпустить Java 9 (надеемся, что переносов сроков больше не произойдёт). Ничто не мешает уже сейчас на предварительной версии проверить, насколько соответствует ожиданиям главная возможность новой версии — модульность (проект Jigsaw).

Уменьшение размера дистрибутива в Java 9 - 1 [1]

В статье описываются изменения, требуемые для сборки дистрибутива с поддержкой модульности. Сборка дистрибутива производится в операционных системах Windows, macOS и Linux.

Полный список новых функций JDK 9 впечатляет [2]. Проект Jigsaw [3] является главной целью версии 9. Предметом данной статьи является составная часть проекта JigsawJEP 275: Modular Java Application Packaging [4] и связанные с ним

В JDK входит утилита командной строки Java Packager [9], позволяющая выполнять компиляцию, сборку, создание цифровой подписи и дистрибутивов Java-приложений. Функции, которые выполняет Java Packager, начиная с JDK 7 Update 6, доступны и в виде задач (tasks) для Ant [10]. В официальной документации они имеют наименование JavaFX Ant Tasks [11], т.к. ранее предназначались в первую очередь для JavaFX-приложений.

JEP 275: Modular Java Application Packaging [4] направлен на интеграцию модульности в Java Packager, в том числе для создания образа JRE, включающего только те модули, которые использует приложение. JavaFX Ant Tasks [11] так же могут быть вызваны и из Maven [12], доминирующего на сегодня инструмента сборки, посредством Maven AntRun Plugin [13].

В экспериментах использовались:

  • операционные системы Windows 10, macOS Sierra 10.12.4, Ubuntu 16.04.2 LTS;
  • JDK 9 Early Access [14] (Build 163 на момент написания статьи) для всех трёх операционных систем;
  • Apache Maven 3.3.9 [15];
  • Inno Setup 5.5.9 [16];
  • IDE с поддержкой Java 9 (например, IntelliJ IDEA 2017.1 [17]).

Код примера доступен на GitHub [18]. Для компиляции и сборки дистрибутива используется Maven. Проект состоит из четырёх частей (модулей в терминологии Maven):

  • консольное (console) приложение без использования модулей (модулей Java 9);
  • консольное приложение с использованием модулей;
  • настольное (desktop) приложение без использования модулей;
  • настольное приложение с использованием модулей.

Сборка дистрибутивов выполняется во всех трёх операционных системах.

Сборка дистрибутива без использования модулей

Процесс сборки дистрибутива состоит из нескольких шагов:

  • компиляция и создание файла JAR;
  • формирование образа JRE;
  • создание дистрибутива, включающих JAR, образ JRE и вспомогательные исполняемые файлы для запуска.

Для создания дистрибутивов в macOS и Linux ничего дополнительно не нужно (кроме JDK и Maven). В операционной системе Windows предварительно необходимо установить Inno Setup [16] или WiX Toolset [19]. Далее подразумевается, что используется Inno Setup.

Создание файла JAR при использовании Maven проще выполнить обычным способом, т.е. используя Apache Maven JAR Plugin [20] (другой способ — использование <fx:jar> [21]). В манифесте (файле MANIFEST.MF) файла JAR, используемом для сборки дистрибутива немодульного (без использования модулей Java 9) приложения, обязательно должен быть указан Main-Class. По этой причине использование вышеуказанного плагина должно быть явно задано с указанием в конфигурации основного класса.

Описание использования задачи <fx:deploy> [22] в файле pom.xml:

Уменьшение размера дистрибутива в Java 9 - 2

Запуск компиляции и сборки дистрибутива в Windows и macOS:

mvn clean package -P native-deploy

Запуск компиляции и сборки дистрибутива в Linux (дополнительно создаётся файл архива tar.gz):

mvn clean package -P native-deploy,tar-gz

Файлы созданного дистрибутива с расширением exe, dmg располагаются в каталоге <module name>/target/deploy/native, с расширением tar.gz — в каталоге <module name>/target.

Добавление использования модулей

На этапе формирования образа JRE неявно будет задействован jlink [5], которому нужно передать информацию об используемых модулях.

Для определения, какие модули Java использует приложение, должна быть вручную запущена утилита jdeps [23]. В версии 9 она дополнительно показывает используемые модули.

jdeps -s <name>.jar

Первое приложение (console) использует единственный модуль java.base, второе (desktop) — модули java.base и java.desktop (вместе с транзитивными модулями, т.к. java.desktop сам зависит от других модулей).

Для первого приложения требуется добавить файл module-info.java, содержащий (указание базового модуля java.base необязательно):

module console.modular {
}

Файл module-info.java для второго приложения должен содержать:

module desktop.modular {
    requires java.desktop;
}

В файле pom.xml появляются обязательные параметры пути к файлам модулей (путь к стандартным модулям $JAVA_HOME/jmods указывать необязательно) и наименования модуля приложения. Включать в качестве ресурса JAR приложения становится излишним, т.к. он уже включён в виде модуля в образ JRE.

Уменьшение размера дистрибутива в Java 9 - 3

Запуск компиляции и сборки аналогичен ранее указанному.

Сравнение результатов

Размер в мегабайтах образа JRE в составе дистрибутива и собственно файла дистрибутива, созданных с использованием Java Packager:

Приложение Windows macOS Linux
образ JRE дистрибутив (exe) образ JRE дистрибутив (dmg) образ JRE дистрибутив (tar.gz)
console-nonmodular 165 36 181 69 204 72
desktop-nonmodular 165 36 181 69 204 72
console-modular 35 9 35 13 44 16
desktop-modular 72 18 75 29 85 31

Размер в мегабайтах образа JRE, созданного при ручном запуске jlink с наиболее оптимальным набором параметров (недоступном из Java Packager):

jlink --module-path <module path> --add-modules <modules> --output <directory> --compress=2 --no-header-files --no-man-pages --strip-debug

Приложение Windows, образ JRE macOS, образ JRE Linux, образ JRE
console-modular 22 21 29
desktop-modular 38 39 49

Сильнее всего размер образа JRE уменьшился на macOS:

  • на 81% скриптом сборки при использовании Java Packager;
  • на 88% при использовании jlink.

Выводы

Значительное уменьшение размеров дистрибутива достигается относительно легко для простых проектов. В случае более сложных проектов, по крайней мере на предварительной версии JDK 9, для решения возникающих проблем может потребоваться изучение кода Java Packager [24].

На проходящих 4 апреля (JBreak 2017 [25] в Новосибирске) и 7-8 апреля (JPoint 2017 [26] в Москве) конференциях можно будет послушать доклады о других интересных возможностях Java 9 и следующих версий Java:

Автор: JUG.ru Group

Источник [34]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/java/251404

Ссылки в тексте:

[1] Image: https://habrahabr.ru/company/jugru/blog/324318/

[2] впечатляет: http://openjdk.java.net/projects/jdk9/

[3] Проект Jigsaw: http://openjdk.java.net/projects/jigsaw/

[4] JEP 275: Modular Java Application Packaging: http://openjdk.java.net/jeps/275

[5] JEP 282: jlink: The Java Linker: http://openjdk.java.net/jeps/282

[6] JEP 220: Modular Run-Time Images: http://openjdk.java.net/jeps/220

[7] JEP 261: Module System: http://openjdk.java.net/jeps/261

[8] JEP 200: The Modular JDK: http://openjdk.java.net/jeps/200

[9] Java Packager: https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/packager.html

[10] Ant: http://ant.apache.org

[11] JavaFX Ant Tasks: https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/javafx_ant_tasks.html

[12] Maven: https://maven.apache.org

[13] Maven AntRun Plugin: http://maven.apache.org/plugins/maven-antrun-plugin

[14] JDK 9 Early Access: https://jdk9.java.net/download/

[15] Apache Maven 3.3.9: https://maven.apache.org/download.cgi

[16] Inno Setup 5.5.9: http://www.jrsoftware.org/isinfo.php

[17] IntelliJ IDEA 2017.1: https://www.jetbrains.com/idea/download/

[18] на GitHub: https://github.com/dbelob/java-package-reduction

[19] WiX Toolset: http://wixtoolset.org

[20] Apache Maven JAR Plugin: https://maven.apache.org/plugins/maven-jar-plugin/

[21] <fx:jar>: https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/javafx_ant_task_reference.html#CIACICBG

[22] <fx:deploy>: https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/javafx_ant_task_reference.html#CIABIFCI

[23] jdeps: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jdeps.html

[24] кода Java Packager: http://hg.openjdk.java.net/openjfx/9/rt/

[25] JBreak 2017: https://2017.jbreak.ru

[26] JPoint 2017: https://jpoint.ru

[27] Functional Reactive with Core Java9: https://jpoint.ru/talks/functional-reactive-with-core-java9/

[28] Going Native: Foreign Functions on the JVM: https://jpoint.ru/talks/going-native-foreign-functions-on-the-jvmj/

[29] Техники векторизации кода в JVM: https://jpoint.ru/talks/vector-programming-in-java/

[30] Повесть о том, как один инженер HTTP/2 Client разгонял: https://jpoint.ru/talks/performance-engineering-story-how-oracle-optimized-http-2-client/

[31] Java 9 Модули. Почему не OSGi?: https://2017.jbreak.ru/talks/java-9-modules-why-not-osgi/

[32] «Преждевременная» компиляция — это нормально?: https://2017.jbreak.ru/talks/compile-ahead-of-time-its-fine/

[33] Java Puzzlers NG S02: Всё чудесатее и чудесатее: https://jpoint.ru/talks/java-puzzlers-ng-s02-down-the-rabbit-hole/

[34] Источник: https://habrahabr.ru/post/324318/