Manifest mf что это
Перейти к содержимому

Manifest mf что это

  • автор:

Что хранится в файле манифеста?

В JAR архиве можно найти файл META-INF/MANIFEST.MF . Это манифест архива – хранилище его метаинформации. Манифест обычно добавляется той же утилитой, которой собирается jar-файл: maven-jar-plugin , команда JDK jar .

Манифест – текстовый файл, который состоит из заголовков, строчек вида ключ: значение . Заголовки разделены на секции. Файл начинается с главной секции, описывающей метаинформацию всего архива. Следом, отделенные пустыми строками, идут секции для отдельных пакетов и файлов. В них могут переопределяться общие заголовки. JVM игнорирует неизвестные ей заголовки, что позволяет сторонним утилитам хранить в манифесте свою специфичную метаинформацию.

Вот некоторые из часто используемых заголовков:
• Информация об архиве: Manifest-Version, Created-By, Multi-Release, Built-By
• Main-class – точка входа приложения
• Classpath приложения
• Информация об экстеншне (Specification и Implementation, deprecated)
• Заголовки OSGI бандла
• Типы и хэши файлов архива (особенно применимо в Android приложениях)

Полный список стандартных заголовков можно почитать в документации.

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

Архив 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.pluginsgroupId>   artifactId>maven-jar-pluginartifactId>   version>3.1.2version>   configuration>   archive>   manifest>   packageName>com.foreach.javapackageName>   manifest>   manifestEntries>   Created-By>foreachCreated-By>   manifestEntries>   archive>   configuration>   plugin> 

Это создает файл манифеста с пользовательским пакетом и заголовками , созданными :

 Manifest-Version: 1.0  Build-Jdk-Spec: 11  Package: com.foreach.java Created-By: foreach 

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

Java: торжественное обращение с jar и атрибутами MANIFEST.MF

Полноценно работать с технологией JAR можно как с помощью утилиты jar, входящей в состав JDK (Java Development Kit), так и с использованием классов JAR API.

Первый способ распространен повсеместно, в то время как второй, зачастую незаслуженно, обделен вниманием и, как показывает практика, напрасно – во многих случаях это может существенно облегчить жизнь разработчика. Именно поэтому в данной статье будут описаны несколько способов применения JAR API для вызова произвольных методов из jar-файла, записи и чтения атрибутов манифеста. (Манифест – (устар.) торжественное письменное обращение верховной власти к народу в связи с важным политическим событием, торжественной датой и т. д. (Толковый словарь русского языка).

Прежде всего следует уделить некоторое внимание утилите jar (http://java.sun.com/javase/6/docs/technotes/tools/solaris/jar.html). Это консольное приложение, запускаемое с набором параметров.

Примеры вызова утилиты:

// Создание нового jar-файла

jar cf file.jar список_файлов

// Просмотр содержимого архива

// Извлечение содержимого из jar-файла

JAR File Specification (http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html), позволяет расположить в архиве file.jar только один манифест с дополнительной служебной информацией META-INF/MANIFEST.MF, представляющий собой текстовый файл в кодировке UTF-8. Если он не был задан при создании jar-файла, используется манифест, который по умолчанию содержит информацию о своей версии и JDK, в которой был создан конкретный jar-файл:

Created-By: 1.6.0 (Sun Microsystems Inc.)

Условно содержимое можно разделить на главную группу (содержит определенные стандартами атрибуты, некоторые из них приведены в таблице 1) и индивидуальную группу (состав которой определяется произвольно).

Таблица 1. Атрибуты главной группы манифеста

Номер версии файла-манифеста. Определяется спецификацией как регулярное выражение следующего вида: цифра+*

Версия и поставщик платформы Java, с помощью которой был создан манифест. Автоматически генерируется утилитой jar

Версия подписи jar-файла. Определяется так же, как и Manifest-Version

Относительные указатели ресурсов (URL) для всех используемых дополнительных классов и библиотек

Относительный путь к главному классу приложения, который должен содержать точку входа – метод main(String[] args). Значение атрибута не должно содержать расширение .class. Атрибут определяется для автономных настольных приложений, которые собраны в выполняемые jar-файлы, которые могут быть запущены виртуальной машиной Java напрямую командой: java -jar file.jar

Имена произвольных атрибутов могут содержать только цифры, строчные и заглавные буквы латинского алфавита и знак «_», а по длине существует ограничение – 70 символов. К значению атрибута никаких требований, кроме элементарной логики, не предъявляется.

Более подробно структуру и состав JAR и META-INF/MANIFEST.MF в рамках этого текста мы затрагивать не будем по той простой причине, что любой желающий может прочесть более подробно cпецификацию JAR.

Использование JAR API

В последней на текущий момент Java 1.6 к JAR API относятся классы пакета java.util.jar, а также классы java.net.JarURLConnection и java.net.URLClassLoader. Ограничимся рассмотрением наиболее используемых классов (см. таблицу 2).

Таблица 2. Наиболее используемые классы в JAR API

Полное название класса

Таблица соответствий между именем атрибута и его значением

Перечисление в виде констант всех имен атрибутов главной группы

Класс описывает элемент jar-файла, например, файл с расширением .class

Наследник класса java.util.zip.ZipFile с поддержкой манифеста. Используется для чтения содержимого jar-файла

Наследник класса java.util.zip.ZipInputStream с поддержкой манифеста. Используется для чтения содержимого jar-файла из любого входящего потока

Наследник класса java.util.zip.ZipOutputStream с поддержкой записи манифеста. Используется для записи содержимого jar-файла в любой исходящий поток

Класс используется для работы с манифестом и его атрибутами

Соединение с jar-файлом или его элементом с помощью указателя ресурсов вида:
ar:!/, например: jar:http://www.site.org/folder/file.jar!/org/site/Clazz.class

Используется для загрузки классов и ресурсов из classpath (может определяться, к примеру, атрибутом манифеста Class-Path)

Запуск методов класса

Прежде всего рассмотрим пример, который будет запускать метод public static void main(String[] args) из произвольного класса в jar-файле. Предположим, что у нас есть некий файл file.jar, который содержит класс pkg.Main:

public class Main

public static void main(String[] args)

MANIFEST.MF архива имеет следующий вид:

Created-By: 1.6.0_03-b05 (Sun Microsystems Inc.)

Вначале необходимо получить URL по имени файла:

URL fileUrl = new File(«file.jar»).toURL();

URL url = new URL(«jar», «», fileUrl + «!/»);

Сам вызов осуществляется следующим образом:

public static final String MAIN_METHOD = «main»;

public void runMainMethod(String className) throws Exception

String[] args = new String[1];

new URLClassLoader(new URL[] < url >);

// Загрузка класса класслоадером

// Получение main-метода и проверка, является ли он точкой входа

mainMethod = clazz.getMethod(MAIN_METHOD, args.getClass());

int mods = mainMethod.getModifiers();

if (mainMethod.getReturnType() != void.class

throw new NoSuchMethodException(MAIN_METHOD);

// Запуск метода с объектом, у которого надо выполнить метод, и параметрами.

// null показывает, что метод статический

Теперь попробуем задействовать JAR API для решения несколько усложненной задачи – теперь необходимо запустить метод main() главного класса jar-файла. Для этого нам надо лишь вызвать уже имеющийся метод runMainMethod() с именем требуемого класса, которое можно получить из манифеста по имени атрибута Main-Class:

private String getMainClassName() throws IOException

JarURLConnection connection = (JarURLConnection) url.openConnection();

Attributes attributes = connection.getMainAttributes();

После вызова метода runMainMethod() в консоли появится надпись:

main(): запущен

Генерация манифеста с атрибутами

После того как мы успешно запустили метод main() главного класса jar-файла, попробуем поработать с атрибутами манифеста. Начнем с создания манифеста, а затем попробуем прочитать записанные атрибуты. Итак, класс JarAttributeWriter будет генерировать все атрибуты:

public class JarAttributeWriter

private static final String LINE_TEMPLATE = «%s: %s\n»;

// Метод генерирует текстовый файл – манифест с именем filename

public void generateManifest(String filename)

StringBuffer buf = new StringBuffer();

InputStream inputStream = new ByteArrayInputStream(buf.toString().getBytes(«UTF-8»));

Manifest manifest = new Manifest(inputStream);

OutputStream outputStream = new FileOutputStream(filename);

> catch (IOException e)

// Метод возвращает одну строку манифеста. Метод format() — аналог printf

// в C – осуществляет форматированный вывод

private String getLine(String attributeName, String attributeValue)

return String.format(LINE_TEMPLATE, attributeName, attributeValue);

В результате файл манифеста будет содержать:

Чтение атрибутов из манифеста

Получившийся файл можно использовать в качестве манифеста для jar-архива – это довольно просто, поэтому предположим, что этот манифест уже лежит в jar-файле и требуется считать из него все атрибуты или только некоторые. Эту работу будет выполнять класс JarAttributeReader:

public class JarAttributeReader

private static final String OUTPUT_TEMPLATE = «%s=%s»;

// Метод считывает все атрибуты из jar-файла filename

Attributes getAllAttributes(String filename) throws IOException

jarFile = new JarFile(filename);

// Метод печатает в консоли атрибуты со значениями

void printAllAttributesWithValues(String filename)

Attributes attributes = getAllAttributes(filename);

for (Object o : attributes.keySet())

System.out.println(String.format(OUTPUT_TEMPLATE, o, attributes.getValue(o.toString())));

> catch (IOException e)

В результате в консоли появится запись следующего вида:

Следует отметить, что JAR API предоставляют довольно мощные средства для работы с JAR вообще и MANIFEST.MF, в частности, которые отнюдь не ограничиваются приведенными выше примерами. Ситуаций, когда правильное использования манифеста может существенно облегчить процесс отладки и/или распространения приложений, довольно много. Например, добавление версии приложения в качестве атрибута MANIFEST.MF позволит точно определить номер сборки приложения. Иными словами, в общем случае, в манифест можно записать различные параметры для последующего их использования при запуске приложения.

Manifest

Манифест – это файл с расширением MF, который создаётся всегда, когда формируется Jar файл (за исключением случая, когда в команде на создание Jar файла указана опция M, не спутайте её с опцией m).

Manifest

Этот создаваемый Jar инструментами манифест назовём манифестом по умолчанию (default manifest). Каждая строка файла манифеста – разделённая двоеточием пара “имя: значение”. Содержание манифеста по умолчанию можно изменить следующим образом. В папке bin нашего проекта создайте текстовый файл MANIFEST.txt, получим:

Введите текст в MANIFEST.txt:

Main-Class: myPack.JarClass

Manifest

и переведите курсор на новую строку, это важно:

Обратите внимание, на картинке курсор в начале новой строки. Сохраните текстовый файл MANIFEST.txt. В MANIFEST.txt мы объявили главный класс приложения. Наш класс находится в пакете myPack, это отражено в MANIFEST.txt: myPack.JarClass.

Ещё раз. Файл манифеста MANIFEST.MF автоматически создаётся всегда (если нет M в команде). Тогда для чего мы создали ещё какой-то MANIFEST.txt? Для того, чтобы изменить содержание дефолтного манифеста, т.е. MANIFEST.MF. При создании файла Jar строки из нашего MANIFEST.txt добавятся в файл MANIFEST.MF.

Создание Jar файла

Правой кнопкой по значку MyJar.bat -> Изменить и вносим такой текст:

jar cfm JARFile.jar MANIFEST.MF myPack/*.class

здесь m – указание на использование нашего текстового файла, а это MANIFEST.txt, для добавления информации в дефолтный манифест;
JARFile.jar – jar файл, который мы создаём;
MANIFEST.txt – наш текстовый файл, который нужен для изменения дефолтного манифеста MANIFEST.MF;
myPack/*.class – указание архивировать все файлы с расширением class из пакета myPack.

Manifest

Получаем:

Manifest

Сохраните MyJar.bat. Теперь можно создать jar файл: два клика по MyJar.bat и через секунду получаем JarFile.jar:

Manifest

Проверим работу полученного JarFile.jar: два раза кликаем по JarFile.jar и видим знакомое окно:

JarFile.jar можно скопировать и поместить копию в любой каталог – она будет работать.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *