← Назад к вопросам

Что такое fat JAR?

2.0 Middle🔥 141 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Что такое Fat JAR (Uber JAR)

Fat JAR (также называется Uber JAR или Shaded JAR) — это JAR файл, который содержит не только скомпилированный код приложения, но и все его зависимости (библиотеки), упакованные вместе. Это позволяет запустить приложение с помощью одной команды: java -jar app.jar.

Сравнение: обычный JAR vs Fat JAR

Обычный JAR

myapp-1.0.jar
├── com/example/...
├── org/springframework/...  ❌ НЕ включены
├── org/slf4j/...           ❌ НЕ включены
└── META-INF/
    └── MANIFEST.MF

Для запуска нужно:
java -cp "myapp-1.0.jar:lib/spring-*.jar:lib/slf4j-*.jar:..." com.example.Main

Fat JAR (Uber JAR)

myapp-1.0-fat.jar
├── com/example/...
├── org/springframework/...
├── org/slf4j/...
├── org/apache/...
└── ... все зависимости внутри

Для запуска:
java -jar myapp-1.0-fat.jar

Зачем нужен Fat JAR

1. Простота развёртывания

  • Один файл вместо множества
  • Не нужно собирать classpath
  • Идеально для Docker контейнеров

2. Переносимость

# Скопировал файл и запустил — работает везде
cp myapp-1.0-fat.jar /path/to/server/
cd /path/to/server/
java -jar myapp-1.0-fat.jar

3. Microservices

# Dockerfile
FROM openjdk:11
COPY target/myservice-1.0-fat.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

4. Отсутствие конфликтов зависимостей

Все версии библиотек зафиксированы в одном файле

Создание Fat JAR: Maven

Способ 1: Maven Assembly Plugin (классический)

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>myapp</artifactId>
    <version>1.0</version>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.0</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.example.Main</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <finalName>myapp-fat</finalName>
                    <appendAssemblyId>false</appendAssemblyId>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Сборка:

mvn clean assembly:assembly
# Результат: target/myapp-fat.jar

Способ 2: Maven Shade Plugin (рекомендуется)

Этот способ решает проблемы с конфликтами имён классов:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.4</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.Main</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

Способ 3: Spring Boot Maven Plugin (для Spring Boot)

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.0</version>
</parent>

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <mainClass>com.example.Application</mainClass>
        </configuration>
    </plugin>
</plugins>

Sборка:

mvn clean package
# Результат: target/myapp-1.0.jar (уже fat jar из коробки)

Создание Fat JAR: Gradle

version = '1.0'

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.0'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.example.Main'
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

Структура Fat JAR

$ unzip -l myapp-1.0-fat.jar | head -50
Archive:  myapp-1.0-fat.jar
  Length     Date   Time    Name
---------  ---------- -----   ----
    1234  2024-01-15 10:30   META-INF/MANIFEST.MF
    5678  2024-01-15 10:30   META-INF/pom.xml
    9012  2024-01-15 10:30   com/example/Main.class
    3456  2024-01-15 10:30   com/example/App.class
   15678  2024-01-15 10:30   org/springframework/core/...  ← Зависимости
   24567  2024-01-15 10:30   org/slf4j/...
   ...

Практический пример: простое приложение

// src/main/java/com/example/Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println("Приложение запущено!");
        
        // Используем зависимость
        ObjectMapper mapper = new ObjectMapper();  // Jackson
        String json = mapper.writeValueAsString(new User("John", 30));
        System.out.println(json);
    }
    
    static class User {
        public String name;
        public int age;
        
        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
}
<!-- pom.xml -->
<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.0</version>
    </dependency>
</dependencies>

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

mvn clean package
java -jar target/myapp-1.0.jar
# Выведет: {"name":"John","age":30}

Плюсы и минусы

Плюсы ✅

  • Простота: Один JAR файл для развёртывания
  • Портативность: Не нужно устанавливать зависимости
  • Docker friendly: Идеально для контейнеризации
  • Отсутствие конфликтов: Все версии зафиксированы
  • Быстрое разворачивание: На сервере не нужно ничего конфигурировать

Минусы ❌

  • Размер: Файл может быть очень большой (50-200MB)
  • Медленный выход: Может занять время на загрузку всех классов
  • Отладка: Сложнее отследить конфликты версий
  • Обновление зависимостей: Нужно пересобирать весь JAR

Оптимизация размера

<!-- Исключить ненужные зависимости -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Запуск с параметрами

# С JVM параметрами
java -Xmx512m -Xms256m -jar myapp-1.0-fat.jar

# С программными параметрами
java -jar myapp-1.0-fat.jar --server.port=8080 --logging.level.root=DEBUG

# С переменными окружения
export APP_NAME="MyApp"
java -jar myapp-1.0-fat.jar

Альтернативы Fat JAR

  • Modulith (Spring) — модульная архитектура
  • Jlink + custom runtime — минимизированная JVM
  • GraalVM Native Image — скомпилированный в машинный код
  • Containerization (Docker) — всё в контейнере

Заключение

Fat JAR — это стандартный способ упаковки Java приложений для production. Он обеспечивает простоту развёртывания и отсутствие проблем с зависимостями. Идеально подходит для microservices, которые разворачиваются в Docker контейнерах.