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

Что такое JAR-манифест?

1.0 Junior🔥 111 комментариев
#Основы Java

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

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

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

Что такое JAR-манифест

JAR-манифест (MANIFEST.MF) — это специальный текстовый файл, который находится в каждом JAR-файле (Java Archive) в директории META-INF/MANIFEST.MF. Манифест содержит метаинформацию о JAR-файле: версию, главный класс, зависимости и другие важные настройки.

Структура JAR файла

my-application.jar
├── META-INF/
│   └── MANIFEST.MF          ← JAR-манифест находится здесь
├── com/
│   └── example/
│       ├── Main.class
│       └── Utils.class
├── application.properties
└── lib/
    └── dependency.jar

Пример простого MANIFEST.MF

Manifest-Version: 1.0
Created-By: 21.0.3 (Oracle Corporation)
Main-Class: com.example.Main
Class-Path: lib/dependency.jar lib/other.jar

Значения в манифесте:

  • Manifest-Version: версия формата манифеста (обычно 1.0)
  • Created-By: версия Java, которая создала JAR
  • Main-Class: главный класс с методом public static void main(String[] args)
  • Class-Path: пути к зависимостям (JAR-файлам)

Создание JAR с собственным манифестом

Способ 1: Простое создание с указанием Main-Class

javac src/Main.java -d bin/
cd bin/
jar cfe my-app.jar com.example.Main *.class

Параметры:

  • c — создать архив
  • f — файл архива
  • e — точка входа (Main-Class)

Это создаст манифест автоматически:

Manifest-Version: 1.0
Created-By: 21.0.3
Main-Class: com.example.Main

Способ 2: Создание собственного файла манифеста

Создай файл MANIFEST.MF:

Manifest-Version: 1.0
Main-Class: com.example.Main
Class-Path: lib/commons-lang3.jar lib/guava.jar
Implementation-Title: My Application
Implementation-Version: 1.0.0
Implementation-Vendor: My Company
Bundle-Version: 1.0.0

Создай JAR с этим манифестом:

javac src/Main.java -d bin/
jar cfm my-app.jar MANIFEST.MF -C bin com/

Параметры:

  • c — создать архив
  • f — файл архива
  • m — использовать внешний манифест

Способ 3: Maven (самый распространённый)

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0</version>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.example.Main</mainClass>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

После mvn package Maven создаст манифест автоматически.

Главные атрибуты манифеста

Main-Class

Указывает класс, который содержит метод main. Позволяет запускать JAR как приложение:

Main-Class: com.example.MyApplication

Запуск:

java -jar my-app.jar

Class-Path

Перечисляет JAR-файлы и директории, которые нужны в classpath:

Class-Path: lib/dependency1.jar lib/dependency2.jar

Пути относительно директории JAR'а. Очень полезно для приложений с зависимостями.

Implementation-Version

Версия приложения:

Implementation-Version: 1.2.3
Implementation-Title: My Application
Implementation-Vendor: My Company

Bundle-Version (OSGi)

Для приложений на основе OSGi (модульность):

Bundle-Version: 1.0.0
Bundle-Name: My Bundle
Bundle-SymbolicName: com.example.bundle

Permissions (Security)

Для приложений, подписанных цифровой подписью:

Implementation-Version: 1.0
Permissions: all-permissions

Чтение манифеста во время выполнения

Можешь программно получить информацию из манифеста:

import java.io.InputStream;
import java.util.jar.Manifest;

public class ManifestReader {
    public static void main(String[] args) throws Exception {
        // Получаем манифест текущего JAR
        Class<?> mainClass = Class.forName("com.example.Main");
        String classPath = mainClass.getProtectionDomain()
            .getCodeSource()
            .getLocation()
            .getPath();
        
        try (InputStream is = new java.util.jar.JarFile(classPath)
            .getInputStream(new java.util.zip.ZipEntry("META-INF/MANIFEST.MF"))) {
            
            Manifest manifest = new Manifest(is);
            String mainClassValue = manifest.getMainAttributes()
                .getValue("Main-Class");
            String version = manifest.getMainAttributes()
                .getValue("Implementation-Version");
            
            System.out.println("Main-Class: " + mainClassValue);
            System.out.println("Version: " + version);
        }
    }
}

Пример: приложение с зависимостями

Структура проекта:

project/
├── src/
│   └── Main.java
├── lib/
│   ├── commons-lang3.jar
│   └── guava.jar
└── MANIFEST.MF

Содержимое MANIFEST.MF:

Manifest-Version: 1.0
Main-Class: Main
Class-Path: lib/commons-lang3.jar lib/guava.jar
Implementation-Title: My Application
Implementation-Version: 1.0.0

Создание JAR:

javac src/Main.java
jar cfm MyApp.jar MANIFEST.MF Main.class

Запуск:

java -jar MyApp.jar

Пример: Spring Boot приложение

Spring Boot автоматически генерирует расширенный манифест:

Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.MyApplication
Spring-Boot-Version: 3.2.0
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Implementation-Title: my-service
Implementation-Version: 1.0.0

Особенности:

  • Main-Class указывает на Spring Boot's JarLauncher
  • Start-Class указывает на реальный класс приложения
  • Spring-Boot-Classes и Spring-Boot-Lib указывают на пути внутри JAR'а

Команды для работы с манифестом

Просмотр содержимого манифеста:

jar xf MyApp.jar META-INF/MANIFEST.MF
cat META-INF/MANIFEST.MF

Обновление манифеста в существующем JAR:

# Нельзя напрямую, нужно переделать JAR
jar cfm MyApp.jar MANIFEST.MF -C classes .

Проверка основного класса:

unzip -p MyApp.jar META-INF/MANIFEST.MF | grep Main-Class

Ошибки и решения

Ошибка: "no main manifest attribute, in MyApp.jar"

Это значит, что не указан Main-Class в манифесте:

// Решение:
jar cfm MyApp.jar MANIFEST.MF *.class
// Где MANIFEST.MF содержит: Main-Class: com.example.Main

Ошибка: "ClassNotFoundException" при запуске

Основной класс не найден. Проверь:

  1. Main-Class правильно указывает на класс с методом main
  2. Класс скомпилирован и находится в JAR

Ошибка: зависимости не найдены

Проверь Class-Path в манифесте и убедись, что зависимости доступны:

Class-Path: lib/dependency.jar

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

Всегда указывай Main-Class для исполняемых JAR-файлов ✅ Используй Class-Path для внешних зависимостей ✅ Добавляй версию (Implementation-Version) для отслеживания ✅ Используй Maven/Gradle для автоматического управления манифестом ✅ Документируй нестандартные атрибуты в README

JAR-манифест — это критическая часть Java-приложения, которая определяет, как оно будет запускаться и работать с зависимостями.