JavaRush /Java блог /Random UA /Кава-брейк #148. Як перетворити будь-яку Java-програму на...

Кава-брейк #148. Як перетворити будь-яку Java-програму на автономний EXE-файл

Стаття з групи Random UA
Джерело: Mccue.dev Сьогодні ви дізнаєтеся, як створити з Java-програми виконуваний EXE-файл для запуску в операційній системі Windows. Кава-брейк #148.  Як перетворити будь-яку Java-програму на автономний EXE-файл - 1Подвійне клацання для запуску — один із найпростіших способів відкрити програму. Якщо у людини, якій ви хочете показати свою програму, вже встановлена ​​правильна версія Java, для запуску вона може двічі клацнути файл jar. Якщо ж у нього не встановлена ​​Java, тобто способи створити установщик, що виконується, такий як jpackage . Після цього для запуску коду потрібно лише натиснути цей установник. Також можна використовувати Native Image , щоб перетворити код на виконуваний файл, який не вимагає будь-якої додаткової установки. У цій статті ми зосередимося на досить простий підхід, який працює для будь-якої програми, незалежно від того, які залежності ви включаєте або які функції JVM використовуєте. Код, про який сьогодні піде мова, можна знайти в репозиторії GitHub , а файли з програмою, що виконуються, викладені тут .

Стек, що використовується

Java 9+

java --version jlink --version

Maven

mvn --version

NodeJS

npx --version

Крок 1. Скомпілюйте та запакуйте свій код у jar

Ця базова програма створить просте вікно з текстом, який можна міняти, натискаючи на одну з кнопок в інтерфейсі.
package example;

import org.apache.commons.text.WordUtils;

import javax.swing.*;
import java.awt.*;

public class Main {
    public static void main(String[] args) {
        var label = new JLabel("Hello, World!");
        label.setFont(new Font("Serif", Font.PLAIN, 72));

        var uppercaseButton = new JButton("Uppercase");
        uppercaseButton.addActionListener(e ->
            label.setText(WordUtils.capitalize(label.getText()))
        );

        var lowercaseButton = new JButton("lowercase");
        lowercaseButton.addActionListener(e ->
            label.setText(WordUtils.uncapitalize(label.getText()))
        );

        var panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.add(label);
        panel.add(uppercaseButton);
        panel.add(lowercaseButton);

        var frame = new JFrame("Basic Program");
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
}
Кава-брейк #148.  Як перетворити будь-яку Java-програму на автономний EXE-файл - 2Зараз наша мета полягає в тому, щоб запакувати код разом з його залежностями у jar. JAR-файли - це звичайні ZIP-архіви з невеликою додатковою структурою. Для проекту Maven конфігурація буде виглядати так.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3 .org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>javaexe</artifactId> <version>1.0</version> <properties> <project.build.sourceEncoding>UTF-8</project .build.sourceEncoding> <maven.compiler.source>18</maven.compiler.source> <maven.compiler.target>18</maven.compiler.target> </properties> <dependencies> <dependency> <groupId> org.apache.commons</groupId> <artifactId>commons-text</artifactId> <version>1.9</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache .maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <executions> <execution> <phase>package</phase> <goals> <goal> shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <manifestEntries> <Main-Class>example.Main</Main- Class> <Build-Number>1.0</Build-Number> </manifestEntries> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
Тут плагін “shade” буде обробляти включення коду з усіх ваших залежностей у jar. В даному випадку єдиною зовнішньою залежністю є org.apache.commons/commons-text .
mvn clean package
Потім ми перемістимо цей jar-файл у новий каталог target/ , де він буде відокремлений від інших файлів.
mkdir build mv target/javaexe-1.0.jar build

Крок 2. Створіть середовище виконання Java (JRE)

Щоб запустити вже створений нами jar-файл, потрібно зв'язати його із середовищем виконання Java. Для цього ми будемо використовувати jlink . Оскільки в екосистемі Java не використовуються модулі, ви, швидше за все, не чули про них і не використовували jlink. Коротше кажучи, jlink може створювати “виконувані образи, що налаштовуються”. Наприклад, ви робите веб-сервер. Вам не потрібні AWT або Swing, тому вмикати їх у код буде зайвим. За допомогою jlink ви можете створити JRE, яка взагалі не включає в себе модуль java.desktop . Ця система працює найкраще, якщо ваш додаток і всі його залежності включають компільовані файли module-info.java , які дають jlink точну інформацію, які модулі ви хочете включити. Ви також можете вручну визначити список необхідних модулів за допомогою ideps . І навіть без модульного проекту ми можемо ефективно клонувати інсталяцію Java в каталог за допомогою jlink.
jlink --add-modules ALL-MODULE-PATH --output build/runtime
Включення кожного модуля окремо дає впевненість у тому, що такі бібліотеки як org.apache.commons/commons-text працюватимуть саме так, як задумано. Потрібно лише з'ясувати, які модулі нам потрібні.

Крок 3. Об'єднайте Jar та JRE у виконуваний файл

Маючи jar-файл, що містить код та всі його залежності, а також JRE, залишається лише об'єднати їх. Для цього нам потрібно виконати такі дії:
  1. Заархівуйте каталог, що містить JRE та jar вашої програми.
  2. Прикріпіть сценарій-заглушку (stub script) до верхньої частини цього zip-файлу, який витягне дані в тимчасовий каталог і запустить код.
Для цього існує бібліотека JavaScript, яка називається caxa . Її мета — перетворювати проекти NodeJS на файли, що виконуються, вона також може об'єднувати будь-які установки NodeJS в системі. На щастя цей крок можна пропустити, вказавши прапор --no-include-node .
npx caxa \ --input build \ --output application \ --no-include-node \ -- ​​"{{caxa}}/runtime/bin/java" "-jar" "{{caxa}}/javaexe-1.0 .jar"
Це створить файл, що виконується, з ім'ям “application”. Якщо ви створюєте його для Windows, потрібно вказати “application.exe”. Коли файл, що виконується, запускається, {{caxa}} буде замінений на тимчасовий каталог, в якому був розгорнутий zip-файл. Зауважте, що при створенні виконуваних файлів використовуються також і такі механізми, як підпис коду та автоматичні оновлення. Однак ці речі вимагають більш глибокого вивчення, яке важко помістити в одну публікацію.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ