Перейти к основному содержимому

Понимание файла манифеста JAR

· 5 мин. чтения

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 Jar
  • Built-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-файлов.