www.samag.ru
Журнал «БИТ. Бизнес&Информационные технологии»      
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Подписка
Архив номеров
Где купить
Авторам
Рекламодателям
Контакты
   

  Опросы
  Статьи

Интеграция Open Source-решений  

Open Source в облачной среде

Облачные решения становятся всё более популярными в мире. Компании стремятся использовать их для

 Читать далее...

Автоматизация  

Нейросеть вам в руки! Как использовать ИИ для автоматизации задач

Использование ИИ для автоматизации задач помогает компании получить конкурентное преимущество, поскольку объединение

 Читать далее...

Рынок труда  

Специалист по этическому ИИ, инженер по квантовым вычислениям или аналитик по метавселенной?

Новые тенденции в развитии ИТ могут привести к возникновению новых специальностей в

 Читать далее...

Книжная полка  

Учитесь убеждать и побеждать

Издательство «БХВ», как всегда, порадовало своих читателей хорошими книжными новинками. Кроме популярных

 Читать далее...

Сетевая инфраструктура  

Как удаленная работа меняет подход к сетевой инфраструктуре?

С увеличением числа сотрудников, работающих из дома, организации сталкиваются с необходимостью создания

 Читать далее...

Мониторинг  

Какой мониторинг нужен сегодня?

По мнению экспертов ГК InfoWatch, действия сотрудников – самая распространенная причина инцидентов

 Читать далее...

Книжная полка  

Руководство для тех, кто увлечен ИИ, программированием. И дизайном

Накануне лета издательство «БХВ» выпустило книжные новинки, от которых любителям чтения будет

 Читать далее...

Мобильные приложения  

Искусственный интеллект в мобильных приложениях: возможности и перспективы

Обзор современных применений ИИ в мобильных приложениях, анализ перспектив развития этой технологии,

 Читать далее...

ИТ-образование  

Как сделать ИТ-образование эффективным?

Эксперты ИТ-отрасли отвечают на вопросы «СА». Обсуждаем ключевые аспекты для улучшения образовательных

 Читать далее...

Work-life balance  

Как айтишнику найти баланс между работой и личной жизнью?

Обсуждаем инструменты для эффективного управления временем, снижения уровня стресса и достижения гармонии. На

 Читать далее...

Книжная полка  

Всё самое нужное – под одной обложкой

Отличительная черта книжных новинок, выпущенных недавно издательством «БХВ» – это их универсальность. Не просто

 Читать далее...

ИТ-инфраструктура  

Системы мониторинга ИТ-инфраструктуры-2025

Без мониторинга ИТ-инфраструктуры не обходится ни одна компания, хотя бы потому, что

 Читать далее...

Открытое ПО  

Безопасность Open Source: рискуем или контролируем?

Компания «Кросс технолоджис» изучила, как используется ПО с открытым кодом в компаниях

 Читать далее...

Работа с нейросетью  

Скажи, есть ли у тебя AI, и я скажу, кто ты

Недавно сервис по поиску работы SuperJob выяснил, что каждый второй россиянин уже

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9639
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 9801
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

12.03.2018г.
Просмотров: 7222
Комментарии: 0
Глубокое обучение с точки зрения практика

 Читать далее...

12.03.2018г.
Просмотров: 4500
Комментарии: 0
Изучаем pandas

 Читать далее...

12.03.2018г.
Просмотров: 5305
Комментарии: 0
Программирование на языке Rust (Цветное издание)

 Читать далее...

19.12.2017г.
Просмотров: 5308
Комментарии: 0
Глубокое обучение

 Читать далее...

19.12.2017г.
Просмотров: 7982
Комментарии: 0
Анализ социальных медиа на Python

 Читать далее...

19.12.2017г.
Просмотров: 4667
Комментарии: 0
Основы блокчейна

 Читать далее...

19.12.2017г.
Просмотров: 4916
Комментарии: 0
Java 9. Полный обзор нововведений

 Читать далее...

16.02.2017г.
Просмотров: 8949
Комментарии: 0
Опоздавших не бывает, или книга о стеке

 Читать далее...

17.05.2016г.
Просмотров: 12388
Комментарии: 0
Теория вычислений для программистов

 Читать далее...

30.03.2015г.
Просмотров: 13928
Комментарии: 0
От математики к обобщенному программированию

 Читать далее...

18.02.2014г.
Просмотров: 15699
Комментарии: 0
Рецензия на книгу «Читаем Тьюринга»

 Читать далее...

13.02.2014г.
Просмотров: 10573
Комментарии: 0
Читайте, размышляйте, действуйте

 Читать далее...

12.02.2014г.
Просмотров: 8600
Комментарии: 0
Рисуем наши мысли

 Читать далее...

10.02.2014г.
Просмотров: 6810
Комментарии: 4
Страна в цифрах

 Читать далее...

18.12.2013г.
Просмотров: 5953
Комментарии: 0
Большие данные меняют нашу жизнь

 Читать далее...

18.12.2013г.
Просмотров: 4872
Комментарии: 0
Компьютерные технологии – корень зла для точки роста

 Читать далее...

04.12.2013г.
Просмотров: 4529
Комментарии: 0
Паутина в облаках

 Читать далее...

03.12.2013г.
Просмотров: 4751
Комментарии: 1
Рецензия на книгу «MongoDB в действии»

 Читать далее...

Друзья сайта  

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

Архив номеров / 2008 / Выпуск №8 (69) / 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

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

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

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

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

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

jar tf file.jar

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

jar xf file.jar

MANIFEST.MF

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-файл:

Manifest-Version: 1.0

Created-By: 1.6.0 (Sun Microsystems Inc.)

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

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

Атрибут

Описание

Manifest-Version

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

Created-By

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

Signature-Version

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

Class-Path

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

Main-Class

Относительный путь к главному классу приложения, который должен содержать точку входа – метод 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

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

Описание

java.util.jar.Attributes

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

java.util.jar.Attributes.Name

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

java.util.jar.JarEntry

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

java.util.jar.JarFile

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

java.util.jar.JarInputStream

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

java.util.jar.JarOutputStream

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

java.util.jar.Manifest

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

java.net.JarURLConnection

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

java.net.URLClassLoader

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

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

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

package pkg;


public class Main {

    public static void main(String[] args) {

           System.out.println("main(): запущен");

    }

}

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

Manifest-Version: 1.0

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

Main-Class: pkg.Main

Вначале необходимо получить 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];

    Class clazz;

    Method mainMethod;

    // Создадим ClassLoader

    URLClassLoader urlClassLoader =

           new URLClassLoader(new URL[] { url });

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

    clazz = urlClassLoader.loadClass(className);

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

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

    mainMethod.setAccessible(true);

    int mods = mainMethod.getModifiers();

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

           || !Modifier.isStatic(mods) || !Modifier.isPublic(mods)) {

           throw new NoSuchMethodException(MAIN_METHOD);

    } else {

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

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

           mainMethod.invoke(null, args);

    }

}

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

private String getMainClassName() throws IOException {

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

Attributes attributes = connection.getMainAttributes();

return attributes.getValue(Attributes.Name.MAIN_CLASS);

}

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

main(): запущен

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

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

import java.io.ByteArrayInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.jar.Manifest;

 

public class JarAttributeWriter {

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

 

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

public void generateManifest(String filename) {

    StringBuffer buf = new StringBuffer();

    buf.append(getLine("Manifest-Version", "1.0"));

    buf.append(getLine("Created-By", this.getClass().getName()));

    buf.append(getLine("Attribute_1", "Value_1"));

    buf.append(getLine("Attribute_2", "Value_2"));

    try {

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

           Manifest manifest = new Manifest(inputStream);

           OutputStream outputStream = new FileOutputStream(filename);

           manifest.write(outputStream);

    } catch (IOException e) {

           e.printStackTrace();

    }

}

 

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

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

private String getLine(String attributeName, String attributeValue) {

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

}

}

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

 

Manifest-Version: 1.0

Created-By: JarAttributeWriter

Attribute_1: Value_1

Attribute_2: Value_2

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

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

import java.io.IOException;

import java.util.jar.Attributes;

import java.util.jar.JarFile;

 

public class JarAttributeReader {

    private static final String OUTPUT_TEMPLATE = "%s=%s";

 

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

    Attributes getAllAttributes(String filename) throws IOException {

           JarFile jarFile;

           Attributes attributes;

 

           jarFile = new JarFile(filename);

           attributes = jarFile.getManifest().getMainAttributes();

           return attributes;

}

 

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

    void printAllAttributesWithValues(String filename) {

    try {

           Attributes attributes = getAllAttributes(filename);

           for (Object o : attributes.keySet()) {

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

    }

    } catch (IOException e) {

           e.printStackTrace();

    }

    }

 

}

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

 

Manifest-Version=1.0

Created-By=JarAttributeWriter

Attribute_1=Value_1

Attribute_2=Value_2

 

Заключение

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


Комментарии отсутствуют

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

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-45
E-mail: sa@samag.ru