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

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

Java-приложения гораздо удобнее собирать в один jar-файл, нежели хранить сложную структуру нескольких тысяч файлов. Однако плюсы использования jar-файлов этим удобством не ограничиваются, иногда может возникнуть необходимость передавать параметры из манифеста.

Многие Java-приложения поставляются в виде одного или нескольких jar-файлов (Java ARchive), которые по сути являются обыкновенными zip-архивами. В них обычно, кроме байт-кода программы, размещаются дополнительные ресурсы и конфигурационные файлы.

Такой подход позволяет:

  • подписывать содержимое jar-файла, повышая таким образом уровень безопасности;
  • сокращать время загрузки апплетов за счет отсутствия необходимости открытия нового соединения для каждого файла;
  • сокращать объем приложения;
  • упростить процесс создания библиотеки;
  • осуществлять контроль версий.

Полноценно работать с технологией 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:<url_к_jar_файлу >!/, например: 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

📎📎📎📎📎📎📎📎📎📎