НейроАгент

Полное руководство: Исполняемый JAR с Maven

Освойте создание исполняемых JAR с помощью Maven с использованием плагинов Shade, Assembly или Exec JAR. Включает примеры конфигурации и советы по устранению неполадок для бесшовного распространения.

Вопрос

Как создать исполняемый JAR-файл со всеми зависимостями с помощью Maven для удобного распространения моего Java-приложения?

НейроАгент

Создание исполняемого JAR со всеми зависимостями с помощью Maven

Для создания исполняемого JAR-файла со всеми зависимостями с помощью Maven можно использовать плагины Maven Assembly Plugin, Maven Shade Plugin или Maven Exec JAR Plugin. Наиболее распространенный подход — использование Maven Shade Plugin, который создает “fat JAR” (жирный JAR), упаковывая все зависимости в один исполняемый JAR-файл, что позволяет запускать ваше приложение с помощью простой команды java -jar your-app.jar.

Содержание


Использование Maven Shade Plugin

Maven Shade Plugin — наиболее популярный выбор для создания исполняемых JAR-файлов со всеми включенными зависимостями. Он упаковывает все зависимости в один JAR-файл и также может создавать исполняемый манифест.

xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.5.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.example.YourMainClass</mainClass>
                            </transformer>
                        </transformers>
                        <filters>
                            <filter>
                                <artifact>*:*</artifact>
                                <excludes>
                                    <exclude>META-INF/*.SF</exclude>
                                    <exclude>META-INF/*.DSA</exclude>
                                    <exclude>META-INF/*.RSA</exclude>
                                </excludes>
                            </filter>
                        </filters>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Shade Plugin предлагает дополнительные возможности, такие как объединение сервисных файлов и обработка дублирующихся классов через секцию <filters>.


Использование Maven Assembly Plugin

Maven Assembly Plugin — еще один вариант, который создает дистрибутивные пакеты, включая ваш JAR-файл и все зависимости в структуре каталогов.

xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.7.1</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.example.YourMainClass</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Assembly Plugin создает JAR-файл с суффиксом “-with-dependencies”, который включает все зависимости в той же структуре, в которой они появляются в вашем проекте.


Использование Maven Exec JAR Plugin

Maven Exec JAR Plugin проще и специально ориентирован на создание исполняемых JAR-файлов с правильной конфигурацией classpath.

xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>com.example.YourMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.6.1</version>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Этот подход создает отдельный каталог lib для зависимостей вместо их упаковки внутри JAR-файла, что может быть полезно для отладки и управления зависимостями.


Настройка главного класса

Независимо от того, какой плагин вы выберете, вам нужно указать главный класс, который должен выполняться при запуске JAR-файла. Это настраивается в манифесте:

xml
<manifest>
    <mainClass>com.example.YourMainClass</mainClass>
</manifest>

Кроме того, вы можете указать главный класс в свойствах вашего pom.xml:

xml
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <mainClass>com.example.YourMainClass</mainClass>
</properties>

Важно: Убедитесь, что указанный вами главный класс действительно существует в вашем проекте и имеет метод public static void main(String[] args).


Распространенные проблемы и решения

Дублирующиеся классы

При использовании Shade Plugin вы можете столкнуться с конфликтами дублирующихся классов. Вы можете справиться с этим следующим образом:

xml
<configuration>
    <filters>
        <filter>
            <artifact>com.example:conflicting-library</artifact>
            <includes>
                <include>com/example/RequiredClass.class</include>
            </includes>
        </filter>
    </filters>
</configuration>

Исключение файлов безопасности

Shade Plugin может не из-за файлов подписи. Исключите их:

xml
<filters>
    <filter>
        <artifact>*:*</artifact>
        <excludes>
            <exclude>META-INF/*.SF</exclude>
            <exclude>META-INF/*.DSA</exclude>
            <exclude>META-INF/*.RSA</exclude>
        </excludes>
    </filter>
</filters>

Проблемы с конфигурацией манифеста

Убедитесь, что ваш манифест правильно настроен с главным классом. Вы можете проверить содержимое манифеста с помощью:

bash
jar tf your-app.jar | grep META-INF/MANIFEST.MF

Лучшие практики

  1. Используйте Shade Plugin для создания настоящих fat JAR — это самый надежный способ создать один исполняемый JAR-файл со всеми зависимостями.

  2. Исключайте ненужные файлы — удаляйте файлы подписи и записи META-INF для уменьшения размера JAR-файла и избежания конфликтов.

  3. Используйте подходящую версию Java — убедитесь, что ваша конфигурация Maven соответствует версии Java, которую вы используете для разработки.

  4. Тестируйте ваш JAR — всегда тестируйте созданный JAR-файл в целевой среде развертывания перед распространением.

  5. Рассмотрите возможность использования нативных образов — для критически важных по производительности приложений рассмотрите возможность использования GraalVM для создания нативных исполняемых файлов вместо JAR.

  6. Используйте управление зависимостями — правильно управляйте вашими зависимостями в секции dependencyManagement вашего pom.xml для избежания конфликтов версий.


Сборка и запуск JAR

Сборка JAR

После настройки соберите ваш исполняемый JAR-файл с помощью Maven:

bash
mvn clean package

Сгенерированный JAR-файл обычно будет находиться в каталоге target/ с именем вроде your-app-1.0.0.jar или your-app-1.0.0-jar-with-dependencies.jar.

Запуск JAR

Запустите ваш исполняемый JAR-файл с помощью:

bash
java -jar target/your-app-1.0.0-jar-with-dependencies.jar

Проверка зависимостей

Вы можете проверить содержимое вашего JAR-файла, чтобы убедиться, что зависимости включены:

bash
jar tf target/your-app-1.0.0-jar-with-dependencies.jar | head -20

Для более детальной проверки:

bash
jar -tf target/your-app-1.0.0-jar-with-dependencies.jar | grep com/example

Заключение

Создание исполняемого JAR-файла со всеми включенными зависимостями с помощью Maven является простым при правильной настройке плагина. Maven Shade Plugin, как правило, является лучшим выбором для создания настоящих fat JAR, в то время как Assembly Plugin предлагает больше гибкости в вариантах упаковки, а Exec JAR Plugin предоставляет более простой подход с отдельными каталогами для зависимостей.

Ключевые рекомендации:

  • Используйте Maven Shade Plugin для большинства приложений, требующих одного исполняемого файла
  • Всегда правильно настраивайте главный класс в вашем манифесте
  • Тщательно тестируйте ваш JAR-файл перед распространением
  • Учитывайте компромиссы между разными подходами в зависимости от ваших потребностей в развертывании

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

Источники

  1. Документация Apache Maven Shade Plugin
  2. Документация Apache Maven Assembly Plugin
  3. Документация Apache Maven JAR Plugin
  4. Лучшие практики для Java Executable JAR