1. Введение
Архив Java (JAR) описывается его файлом манифеста. В этой статье рассматриваются его многочисленные возможности, в том числе добавление атрибуции, создание исполняемого файла JAR и встраивание информации о версиях.
Однако давайте начнем с краткого обзора того, что такое файл манифеста.
2. Файл манифеста
Файл манифеста называется MANIFEST.MF
и находится в каталоге META-INF
в JAR. Это просто список пар ключ-значение, называемый заголовками
или атрибутами
, сгруппированный в разделы.
Эти заголовки
предоставляют метаданные, которые помогают нам описывать аспекты нашего JAR, такие как версии пакетов, какой класс приложения выполнять, путь к классам, материал подписи и многое другое.
3. Добавление файла манифеста
3.1. Манифест по умолчанию
Файл манифеста добавляется автоматически всякий раз, когда мы создаем JAR .
Например, если мы создадим JAR в OpenJDK 11:
jar cf MyJar.jar classes/
Он создает очень простой файл манифеста:
Manifest-Version: 1.0
Created-By: 11.0.3 (AdoptOpenJDK)
3.2. Пользовательский манифест
Или мы можем указать наш собственный файл манифеста.
Например, предположим, что у нас есть пользовательский файл манифеста с именем manifest.txt
:
Built-By: foreach
Мы можем включить этот файл, и jar объединит
его с файлом манифеста по умолчанию, когда мы используем параметр m
:
jar cfm MyJar.jar manifest.txt classes/
Затем результирующий файл манифеста:
Manifest-Version: 1.0
Built-By: foreach
Created-By: 11.0.3 (AdoptOpenJDK)
3.3. Мавен
Теперь содержимое файла манифеста по умолчанию меняется в зависимости от того, какие инструменты мы используем.
Например, Maven добавляет несколько дополнительных заголовков:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.3.9
Built-By: foreach
Build-Jdk: 11.0.3
На самом деле мы можем настроить эти заголовки в нашем файле pom.
Скажем, например, что мы хотим указать, кем был создан JAR и пакет:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<archive>
<manifest>
<packageName>com.foreach.java</packageName>
</manifest>
<manifestEntries>
<Created-By>foreach</Created-By>
</manifestEntries>
</archive>
</configuration>
</plugin>
Это создает файл манифеста с пользовательским пакетом
и заголовками , созданными :
Manifest-Version: 1.0
Build-Jdk-Spec: 11
Package: com.foreach.java
Created-By: foreach
Полный список параметров см. в документации подключаемого модуля Maven JAR .
4. Заголовки
Заголовок должен соответствовать определенному формату и отделяться новой строкой:
key1: value1
Key2: value2
Действительный заголовок должен иметь пробел между двоеточием и значением . Еще один важный момент — в конце файла должна быть новая строка . В противном случае последний заголовок игнорируется.
Давайте рассмотрим некоторые стандартные заголовки из спецификации и некоторые распространенные настраиваемые заголовки.
4.1. Основные заголовки
Основные заголовки обычно содержат общую информацию:
Manifest-Version
: версия спецификации.Created-By
: версия инструмента и поставщик, создавший файл манифеста.Multi-Release
: еслиtrue
, то это Multi-Release JarBuilt-By
: этот настраиваемый заголовок содержит имя пользователя, создавшего файл манифеста.
4.2. Точка входа и путь к классам
Если наш JAR содержит работающее приложение, мы можем указать точку входа. Точно так же мы можем указать путь к классам
. Поступая таким образом, мы избегаем необходимости указывать его, когда хотим его запустить.
Main-Class
: пакет и имя класса с основным методом (без расширения .class)Class-Path
: разделенный пробелами список относительных путей к библиотекам или ресурсам.
Например, если наша точка входа в приложение находится в Application.class
и использует библиотеки и ресурсы, мы можем добавить необходимые заголовки:
Main-Class: com.foreach.Application
Class-Path: core.jar lib/ properties/
Путь к классам включает core.jar
и все файлы в каталогах lib
и properties
. Эти активы загружаются относительно места выполнения JAR, а не из самого JAR . Другими словами, они должны существовать вне JAR.
4.3. Версия упаковки и запечатывание
Эти стандартные заголовки описывают пакеты в JAR.
Название
: пакетРеализация-Build-Date
: дата сборки реализации.Реализация-название
: название реализацииРеализация-
вендор : поставщик реализацииРеализация-Версия
: версия реализацииSpecification-Title
: название спецификации.Specification-Vendor
: поставщик спецификацииВерсия
спецификации: версия спецификацииSealed
: если true, то все классы для пакета взяты из одного и того же JAR (по умолчанию false)
Например, мы находим эти заголовки манифеста в драйвере MySQL Connector/J JAR . Они описывают версию спецификации JDBC, которой соответствует JAR, а также версию самого драйвера:
Specification-Title: JDBC
Specification-Version: 4.2
Specification-Vendor: Oracle Corporation
Implementation-Title: MySQL Connector/J
Implementation-Version: 8.0.16
Implementation-Vendor: Oracle
4.4. Подписанная банка
Мы можем подписать наш JAR цифровой подписью, чтобы добавить дополнительную безопасность и проверку. Хотя этот процесс выходит за рамки данной статьи, он добавляет в файл манифеста стандартные заголовки, показывающие каждый подписанный класс и его закодированную подпись . Дополнительные сведения см. в документации по подписанию JAR .
4.5. ОСГИ
Обычно также можно увидеть пользовательские заголовки для пакетов OSGI:
Название пакета
: названиеBundle-SymbolicName
: уникальный идентификаторBundle-Version
: версияImport-Package
: пакеты и версии, от которых зависит пакет.Export-Package
: набор пакетов и версий, доступных для использования.
См. нашу статью «Введение в OSGI », чтобы узнать больше о пакетах OSGI.
5. Разделы
В файле манифеста есть два типа разделов: основной и для каждой записи. Заголовки, которые появляются в основном разделе, применяются ко всему в JAR . Принимая во внимание , что заголовки, которые появляются в разделах для каждой записи, относятся только к именованному пакету или классу .
Кроме того, заголовок, появляющийся в разделе для каждой записи, переопределяет тот же заголовок в основном разделе. Разделы для каждой записи обычно содержат информацию о версиях пакетов и пломбировании, а также цифровую подпись.
Давайте рассмотрим простой пример раздела для каждой записи:
Implementation-Title: foreach-examples
Implementation-Version: 1.0.1
Implementation-Vendor: ForEach
Sealed: true
Name: com/foreach/utils/
Sealed: false
Основной раздел вверху запечатал все пакеты в нашем JAR. Однако пакет com.foreach.utils
распечатывается разделом для каждой записи.
6. Заключение
В этой статье представлен обзор того, как добавить файл манифеста в JAR, как использовать разделы и некоторые общие заголовки. Структура файла манифеста позволяет нам предоставлять стандартную информацию, такую как информация о версии.
Однако его гибкость позволяет нам определять любую информацию, которую мы считаем уместной для описания содержимого наших JAR-файлов.