Обычно удобно объединять множество файлов классов Java в один архивный файл.
В этом уроке мы рассмотрим все тонкости работы с jar – или J ava AR chive – файлами на Java.
В частности, мы возьмем простое приложение и рассмотрим различные способы его упаковки и запуска в виде jar. Мы также ответим на некоторые любопытные вопросы, такие как как легко прочитать файл манифеста jar по пути.
2. Настройка программы Java
Прежде чем мы сможем создать запускаемый jar-файл, наше приложение должно иметь класс с основным методом . Этот класс обеспечивает нашу точку входа в приложение:
public static void main(String[] args)
3. Команда Jar
Теперь, когда мы все настроили, давайте скомпилируем наш код и создадим наш jar-файл.
Компиляция и запуск Java без IDE
Недавний поток Java subreddit под названием « Компиляция пакетов Java без IDE » поставил вопрос: «Есть ли [там] команда, которая собирает группу java-файлов, которые находятся внутри пакета, в отдельную папку (давайте просто назовем это bin), и как я пойду о запуске новых файлов классов? » Автор поста, kylolink , объясняет, что «когда я начал использовать Java, я полагался на Eclipse, чтобы выполнить всю компиляцию для меня, и просто беспокоился о написании кода». Я неоднократно сталкивался с этой проблемой, и, собственно, именно это побудило мою (сейчас 4 года) публикацию в блоге системы GPS и IDE: полезно или вредно? Мне нравятся мощные современные Java IDE, и они ежедневно облегчают мою жизнь, но есть преимущества в том, чтобы знать, как создавать и запускать простые примеры Java без них. Этот пост посвящен тому, как это сделать.
Программирование на Java: создание игры Змейка. Часть 1.
В своем блоге « Изучение Java с помощью простых тестов» я писал о том, как иногда мне нравится использовать простой текстовый редактор и инструменты командной строки для написания, создания и запуска простых приложений. Теперь у меня есть довольно хорошее представление о том, сколько требуют мои «накладные расходы» для моих любимых Java IDE, и я принимаю решение о том, достаточны ли преимущества, достигнутые от использования IDE, чтобы оправдать «накладные расходы». В большинстве реальных приложений нет сомнений, что накладные расходы IDE того стоят. Однако для самых простых примеров приложений это не всегда так. Остальная часть этого поста показывает, как создавать и запускать код Java без IDE для этих ситуаций.
Код Java, который будет построен и выполнен
Чтобы сделать обсуждение этого поста более конкретным, я буду использовать некоторые очень простые классы Java, которые связаны друг с другом посредством композиции или наследования и находятся в одном и том же именованном пакете (не в неназванном пакете ), называемом dustin.examples . Два из классов не имеют main функций, а третий класс Main.java имеет main функцию, позволяющую продемонстрировать запуск класса без IDE. Список кодов для трех классов показан ниже.
Parent.java
package dustin.examples;
public class Parent
public String toString()
return «I’m the Parent.» ;
Сделал Java программу с интерфейсом / Погодное приложение
Child.java
package dustin.examples;
public class Child extends Parent
public String toString()
return «I’m the Child.» ;
Main.java
package dustin.examples;
import static java.lang.System.out;
public class Main
private final Parent parent = new Parent();
private final Child child = new Child();
public static void main( final String[] arguments)
final Main instance = new Main();
out.println(instance.parent);
out.println(instance.child);
На следующем снимке экрана показана структура каталогов с этими исходными файлами класса .java . Снимок экрана показывает, что исходные файлы находятся в иерархии каталогов, представляющей имя пакета ( dustin/examples из-за пакета dustin.examples ), и что эта иерархия каталогов, отражающая пакет, находится в подкаталоге с именем src . Я также создал подкаталог classes (который в настоящее время пуст) для размещения скомпилированных файлов .class потому что javac не будет создавать этот каталог, когда он не существует.
Сборка с javac и бег с java
Независимо от того, какой подход используется для создания кода Java (Ant, Maven, Gradle или IDE), он в конечном итоге сводится к javac . Стандартные параметры инструмента командной строки javac, предоставляемые Oracle / Sun, можно увидеть, запустив javac -help а дополнительные параметры расширения можно просмотреть, запустив javac -help -X . Более подробную информацию о том, как применять эти параметры, можно найти в документации по инструментам для javac для Windows или Unix / Linux .
Как указано в документации javac , параметр -sourcepath может использоваться для выражения каталога, в котором находятся исходные файлы. В моей структуре каталогов, показанной на снимке экрана выше, это будет означать, что, если я запускаю команду javac из каталога C:javaexamplesjavacAndJava , мне нужно иметь что-то подобное в моей команде: javac -sourcepath src srcdustinexamples*.java . Следующий снимок экрана показывает результаты этого.
Поскольку мы не указали каталог назначения для файлов .class , по умолчанию они были помещены в тот же каталог, что и исходные файлы .java из которых они были скомпилированы. Мы можем использовать опцию -d чтобы исправить эту ситуацию. Наша команда может быть выполнена сейчас, например, как javac -sourcepath src -d classes srcdustinexamples*.java . Как указано ранее, указанный целевой каталог ( classes ) уже должен существовать. Когда это произойдет, команда поместит файлы .class в назначенный каталог, как показано на следующем снимке экрана.
С исходными файлами Java, скомпилированными в соответствующие .class в указанном каталоге, теперь мы можем запустить приложение с помощью инструмента командной строки средства запуска приложения Java java . Это просто сделать, следуя инструкциям, показанным java -help или страницей инструментов java, и указав расположение файлов .class с -classpath (или -cp ). Использование обоих подходов для указания того, что каталог classes находится там, где нужно искать .class продемонстрировано на следующем снимке экрана. Последний аргумент — это полное имя (весь пакет Java) имени класса, у которого есть main функция, которая должна быть выполнена. Команды, показанные на следующем снимке экрана, представляют собой java -cp classes dustin.examples.Main java -classpath classes dustin.examples.Main java -cp classes dustin.examples.Main и java -classpath classes dustin.examples.Main .
Сборка и бег с муравьем
Для простейших приложений Java довольно просто использовать javac и java для сборки и выполнения приложения соответственно, как только что продемонстрировано. Поскольку приложения становятся немного более вовлеченными (например, код, существующий в более чем одном пакете / каталоге, или более сложные зависимости пути к классам от сторонних библиотек и сред), этот подход может стать громоздким. Apache Ant является старейшим из «большой тройки» инструментов сборки Java и используется в тысячах приложений и развертываний. Как я уже говорил в предыдущем посте в блоге , очень просто создать очень простой файл сборки Ant, особенно если он начинается с шаблона, который я описал в этом посте .
Следующий листинг кода предназначен для файла Ant build.xml который можно использовать для компиляции файлов .java файлы .class а затем запустить класс dustin.examples.Main как это было сделано выше для javac и java .
Источник: coderlessons.com
Сборка и выполнение Java программ
Сборка (англ. assembly) — двоичный файл, содержащий исполняемый код программы или (реже) другой подготовленный для использования информационный продукт.
Автоматизация сборки — этап написания скриптов или автоматизация широкого спектра задач применительно к ПО, применяемому разработчиками в их повседневной деятельности, включая такие действия, как:
- компиляция исходного кода в бинарный код
- сборка бинарного кода
- выполнение тестов
- разворачивание программы на производственной платформе
- написание сопроводительной документации или описание изменений новой версии
Для автоматизации сборки проектов традиционно используют системы сборки, такие как make на Unix подобных системах и nmake для компилятора Microsoft. Также традиционно написание файлов для сборки проекта под эти системы является задачей нетривиальной. Конечно, пользуясь только Mictosoft Visual Studio можно даже не подозревать о существовании этих файлов, так как интегрированная среда разработки достаточно удобно скрывает всю схему работы, оставляя снаружи несколько диалоговых окон и кнопку Build. Но для сложных проектов использующих массу сторонних библиотек и кроссплатформенных проектов такой подход часто оказывается неприемлемым.
Принципы сборки в java
1. Как работает java компилятор
Текст программы — это исходный код программы на языке java.
Дополнения — это классы, которые необходимо учитывать во время сборки (библиотеки).
В итоге мы получаем набор файлов с расширением class. То есть, если мы используем сторонние библиотеки – мы должны указать их при сборке. Это могут быть скомпилированные классы или собранные подсистемы.
Не всегда для компиляции необходимо указывать дополнительные библиотеки (к примеру, если у нас программа в 1 программный файл). Но если всё же это необходимо, то для этого компилятор java необходимо запустить с аргументом «-cp» (сокращение от –classpath). После этого аргумента идёт список библиотек (jar файлов или файлов class) разделённых символом разделителем файлов (в *nix это «:», в windows это «;»).
Пример компиляции программы из одного файла:
javacHelloWorld.java
Пример компиляции программы c дополнительными библиотеками «myLib» и «my2ndLib»:
javac -cp myLib.jar:my2ndLib.jar NotStandartHelloWorld.java
В java нет разграничения между собранной библиотекой, исполняемым приложением или же подсистемой. Что имеется в виду, что если вы хотите создать самостоятельную сущность в едином файле, вы создаёте jar файл. К примеру, если вы создаёте библиотеку, то это будет jar файл с набором классов, который могут быть использованный другими разработчиками, если это подсистема, то это часть функционала (набор классов) вынесенная за рамки основного модуля, но используемая в нём (что то вроде частной библиотеки), и т.д..
2. Выполнение java-программы.
Выполнение классов работает схожим образом с компиляцией (используются даже те же аргументы).
Если после компиляции у нас получилось 10 классов, то выполняем только класс который содержит функцию main, остальные классы должны быть представлены как библиотеки.
К примеру, запуск программы c дополнительными библиотекой «sout», которая находиться в папку «lib» выглядеть так:
java -cp lib/sout.jar HelloWorld
По умолчанию, все классы в текущем каталоги включены в пути (-cp для классов в текущем каталоге указывать не надо). Что имеется в виду, если мы скомпилировали программу, и в итоге получили множество классов в одной папке, то мы можем запускать только лишь главный класс, остальные классы java попробует найти сама в текущем каталоге (Даже если они находятся во вложенных папках, java и туда заглянет).
Такой подход допустим, когда у нас немного классов, но при больших системах перечисление всех классов не возможно (их количество может превышать тысячи …). Поэтому можно выполнять не класс, а специально собранный jar-файл. Для этого необходимо указать аргументы -jar.
java -cp lib.jar -jar myApp.jar
3. Jar-файл
Jar-файл — это ZIP архив (то есть вы можете разархивировать его). Jar-файл должен в себе содержать набор классов и файл META-INF/MANIFEST.MF, в котором описаны характеристики данного jar-файла.
Основной вариант создания Jar-файла:
jar cf jar-file input-file(s)
Jar – это утилита и набора утилит которые вы получаете при установке java.
Программа jar принимает аргументы в old-UNIX стиле: вначале идут ключи потом аргументы программы, ключ с аргументом указывается последним, не указывать «-» перед аргументами, группировать короткие аргументы («cf» значит «-c -f »).
- Опция c — говорит о том, что вы хотите создать (create) jar-файл.
- Опция f — говорит о том, что вы хотите создать файл (file) с определённым именем (при выполнении данного примера создастся файл с именем «jar-file.jar»).
- Аргумент input-file(s) является разделенный пробеламисписок из одного или нескольких файлов, которые вы хотите включить в ваш JAR-файл. input-file(s) аргумент может содержать символ «*». Если любой из входных является каталогом, содержимое этих каталогов добавляются в архив JAR рекурсивно.
Когда вы создаете JAR-файл, он автоматически получает файл манифеста по умолчанию (если вы его не указали во входных файлах – он будет создан автоматически). В jar-файле может быть только один файл манифеста с указанным путём:
Общая структура манифеста имеет вид:
Все символы пробелов (n, r, t, …) в «значении» будут удалены, к примеру, манифест:
Manifest-Version: 1.0Созданная-By: 1.6.0 (Sun Microsystems Inc) |
Когда вы создаете JAR-файл, по умолчанию файл манифеста просто содержит следующее:
Manifest-Version: 1.0Созданная-By: 1.6.0 (Sun Microsystems Inc) |
Эти строки показывают, что элементы манифеста имеют форму “заголовок: значение” пар. Имя заголовка отделяется от ее значения двоеточием. Манифест по умолчанию соответствует версии 1.0 спецификации манифест и был создан 1.6.0 версии JDK.
Манифест также могут содержать информацию о других файлах, которые не упакованы в архив (внешние библиотеки который необходимы для функционирования, об этом будет сказано более подробно дальше). Именно то, что информацию о jar-файле должна быть записаны в манифесте зависит от того, как вы собираетесь использовать JAR-файл. Манифест по умолчанию не делает никаких предположений о том, какую информацию он должен записать о других файлах.
Чтоб создать jar-файл с манифестом:
jar cfm jar-file manifest-addition input-file(s)
Ключ «f» и «m» оба требуют аргументов, поэтому мы вначале указываем ключи, а потом в том же порядке указываем (если это необходимо) недостающее аргументы. В начале мы указали аргумент «f», а потом «m», поэтому первый аргумент будет имя выходного файла, а второй это имя (и путь) к манифесту.
Если в написанном вами манифесте не будет одной из выше указанных опций, то они будут добавлены автоматически (то есть, ну указать манифест или указать пустой файл, это одно и то же, это часто применимо в начале разработки…). То, есть если ваш манифест выглядит следующим образом:
Main-Class: Main |
То, в итоговом jar-файле он будет представлен в виде:
Manifest-Version: 1.0Созданная-By: 1.6.0 (Sun Microsystems Inc)Main-Class: Main |
Если вы разрабатываете приложение, которое поставляется в JAR-файл, необходимо каким-то образом указать, какой класс в JAR-файле является входной точкой приложения (который содержит функцию main). Вы предоставляете эту информацию с Main-Class заголовка в манифесте, который имеет общий вид:
Main-Class: имя класса |
Значение имени класса является именем класса, который является входной точкой приложения.
После того как вы установите Main-Class заголовка в манифесте, вы запустите файл JAR с помощью следующей формы Java команду:
java -jar JAR-file
Не указав главного класса в манифесте вам придаться выполнять вашу программу так:
java -cp JAR-file.jar MainClass
Если вы хотите указать лишь главный класс в манифесте, то вам не нужно создавать весь манифест, вы можете указать, необходимы параметр при вызове jar:
jar cfe app.jar MyApp MyApp.class
Опция e — говорит о точки входа в программу (entrypoint).
Вам придется ссылаться на классы в другие файлы JAR из JAR-файла (если вы используете сторонние библиотеки в своем приложении). Для этого вам необходимо включить следующие поля в манифест:
Class-Path: jar1-name jar2-name directory-name/jar3-name |