Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое 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 JarLauncherStart-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" при запуске
Основной класс не найден. Проверь:
Main-Classправильно указывает на класс с методомmain- Класс скомпилирован и находится в JAR
Ошибка: зависимости не найдены
Проверь Class-Path в манифесте и убедись, что зависимости доступны:
Class-Path: lib/dependency.jar
Лучшие практики
✅ Всегда указывай Main-Class для исполняемых JAR-файлов ✅ Используй Class-Path для внешних зависимостей ✅ Добавляй версию (Implementation-Version) для отслеживания ✅ Используй Maven/Gradle для автоматического управления манифестом ✅ Документируй нестандартные атрибуты в README
JAR-манифест — это критическая часть Java-приложения, которая определяет, как оно будет запускаться и работать с зависимостями.