Что такое Fat JAR (Uber JAR) и как его создать?

Ответ

Fat JAR (или Uber JAR, Shadow JAR) — это исполняемый JAR-архив, который содержит не только скомпилированные классы вашего приложения, но и все его зависимости (библиотеки из META-INF, lib и т.д.), упакованные в один файл.

Зачем это нужно? Упрощает развертывание: для запуска приложения требуется только JRE и один файл JAR, без необходимости отдельно управлять библиотеками.

Как создать с помощью Maven:

  1. Плагин maven-assembly-plugin:

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.example.Main</mainClass> <!-- Укажите главный класс -->
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    После mvn clean package в target/ появится your-artifact-jar-with-dependencies.jar.

  2. Плагин spring-boot-maven-plugin (для Spring Boot): Создает Fat JAR по умолчанию.

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

Недостатки Fat JAR:

  • Размер: Файл становится очень большим.
  • Конфликты: Возможны конфликты файлов (например, META-INF/MANIFEST.MF или spring.factories) из разных библиотек.
  • Обновления: Для обновления одной библиотеки необходимо пересобрать и переразвернуть весь JAR.

Альтернатива: Использование модульной системы (JPMS) или сборка с помощью jlink для создания минимального образа среды выполнения.

Ответ 18+ 🔞

Давай разберемся с этим жирным банкой, а то народ путается, как сука в тапках на льду.

Вот представь: ты написал приложение, а там дохуя библиотек — Spring, Hibernate, какие-то утилиты. Обычный JAR — это как твой код в пустом чемодане, а все зависимости — это ещё три телеги баулов, которые надо тащить отдельно. А Fat JAR (он же Uber JAR, он же Shadow JAR) — это когда ты, блядь, берешь весь свой код, все эти библиотеки, всю эту хуйню, и тупо засовываешь в один здоровенный чемодан. Один файл — и всё внутри. Красота, ёпта!

Нахуя это надо? Да чтобы не ебаться! Развернул — один файл скопировал, java -jar твой_жирный_банк.jar запустил, и поехало. Никаких танцев с -cp, никаких lib папок. Идеально для демо, для микросервисов в контейнерах, да и просто чтобы не сойти с ума.

Как его смастырить на Maven? Есть два основных пути, как в той сказке.

1. Старый добрый maven-assembly-plugin — как топором вырубить.

Это классика, прям как Герасим из «Муму» — сильный, простой, но может и нахуй всё замочить, если не аккуратно. Конфиг в pom.xml:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <!-- СЮДА, БЛЯДЬ, ГЛАВНЫЙ КЛАСС ВПИШИ, А ТО НИЧЕГО НЕ ЗАПУСТИТСЯ! -->
                        <mainClass>com.example.Main</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <!-- А это волшебное слово, чтобы всё в кучу собрало -->
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase> <!-- Сработает на фазе package -->
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Выполнишь mvn clean package, и в target/ появится не только обычный JAR, но и второй — your-artifact-1.0-jar-with-dependencies.jar. Вот он и есть наш жирный красавец.

2. Каноничный spring-boot-maven-plugin — для изнеженных спринг-пацанов.

Если ты на Spring Boot, то даже думать не надо. Этот плагин по умолчанию создаёт Fat JAR, да ещё и со своим, блядь, загрузчиком классов, который конфликты решает умнее. Просто добавь в pom.xml:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Запустил mvn package — и готово. В target будет твой your-app-0.0.1-SNAPSHOT.jar. Он уже жирный и готовый к бою.

Но не всё так гладко, как попа мартышлюшки! Есть и подводные ебучки:

  • Размер, овердохуища! Файл может весить сотни мегабайт. Каждое обновление — качаешь эту тушу заново.
  • Конфликты, пиздец! У двух библиотек может быть файл с одинаковым именем, например, META-INF/services/что-то-там. Кто из них останется в итоговом JAR? Угадай с трёх раз. Классический assembly может просто взять первого попавшегося и на этом успокоиться.
  • Обновлять — боль. Захотел обновить одну мелкую либу на новую версию? Придётся пересобирать и перевыкатывать всю эту махину целиком, а не один маленький файлик.

Так что делать, если жирный банк — не вариант? Есть альтернативы! Можно модульную систему (JPMS) освоить или jlink использовать, чтобы собрать свою минимальную JRE только с нужными модулями. Но это уже, как говорится, другая история, блядь, для тех, кто не ищет лёгких путей.

Короче, Fat JAR — инструмент мощный, но тупой как валенок. Используй с умом, и будет тебе счастье. А нет — сам потом разгребай последствия, в рот меня чих-пых.