Программирование в IDE — прекрасно: связанность зависимостей кода, удобный дебаг, понятное тестирование, темная тема. Так вот, благодаря IDE разработка развивается семимильными шагами. Но она расслабляет. С каждым днем, погружаясь в функционал IDE, разработчик привыкает к коммиту одной кнопкой или сборке двумя кликами.
Гораздо хуже обстоит ситуация с новичками в программировании, которые с самого начала работают в IDE, игнорируя работу в командной строке. Например, в Intellij IDEA компиляция Java приложения демонстрируется загрузочным баром в нижней панели, а все параметры компиляции, обработка classpath и прочих прелестей Java-жизни остается за кадром.
Предлагаем поговорить о компиляции в Java без IDE. Для запуска примеров в статье следует убедиться, что на вашей машине установлена JDK 1.7 и старше.
Как скомпилировать программу?
Компиляция в программировании — это приведение исходного кода в байт-код для последующего старта программы. Порядок действий от исходного кода до запуска программ выглядит так:- Есть исходный код в файле с именем НазваниеКласса.java;
- Если в коде нет ошибок, он компилируется в байт-код (в файл НазваниеКласса.class);
- Программа запускается.
class Test {
public static void main(String[] args) {
System.out.println("Это говорит приложение из командной строки");
}
}
Для чего нужна команда javac
Окей, первый пункт выполнен. Идем дальше, чтобы понять: скомпилировать — это как? :) В этом нам поможет команда javac, в аргументе которой необходимо указать нужный файл:
javac Test.java
Если нет ошибок в коде, рядом с файлом Test.java появится файл Test.class. Это и есть скомпилированный байт-код. Теперь его нужно запустить. Здесь используется команда java, запускающая байт-код:
На скриншоте видно, что в выводе получаем какие-то иероглифы: очевидно, это сбитая кодировка. Как правило это происходит в системе Windows. Для корректного отображения кириллицы в консоли, есть следующие команды:
REM change CHCP to UTF-8
CHCP 65001
CLS
Они меняют текущую кодовую страницу командной консоли на время работы текущего окна.
Попробуем еще раз:
D:\Java>java Test
Это говорит приложение из командной строки.
Знать принцип работы команды javac очень полезно, так как эта команда лежит в основе любой системы сборки проектов.
Компиляция и выполнение нескольких классов
Для работы с несколькими классами нужен classpath. Он похож на файловую систему, в которой содержатся классы, а функцию папок выполняют пакеты (packages). На этом этапе стоит задуматься об отделении файлов исходного кода от скомпилированных файлов. Как правило исходники находятся в каталоге src, а скомпилированные классы — в bin. Например, у нас есть классBox
и класс BoxMachine
, в котором содержится метод main
.
Класс Box
:
package src;
public class Box {
private double size;
public Box(double size) {
this.size = size;
}
public String toString() {
return "Box have size " + size;
}
}
Он находится в пакете src, это необходимо зафиксировать.
Класс BoxMachine
:
package src;
public class BoxMachine {
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
System.out.println(new Box(Math.random()*10));
}
}
}
Этот класс также находится в пакете src. В методе main
он создает пять объектов класса Box
разного размера и выводит в консоль информацию о них.
Чтобы скомпилировать эту группу классов, необходимо из главного каталога (в котором лежат папки src и bin) использовать команду javac с аргументами:
javac -d bin ./src/*
-d
— флаг, после которого следует указать расположение, куда попадут скомпилированные классы. Это очень удобно, так как перекладывать, например, 1000 классов — очень трудоемкий процесс.
bin
— название папки.
./src/*
— расположение исходных файлов. *
указывает, что необходимо скомпилировать все файлы.
Теперь скомпилированные классы появились в папке bin. Для их запуска используется команда java из той же директории, также с аргументами:
java -classpath ./bin BoxMachine
-classpath
— флаг, после которого следует указать местоположение скомпилированных классов. Java будет искать главный класс и все сопутствующие именно в этой директории.
./bin
— название папки, в которой находятся скомпилированные классы.
BoxMachine
— название главного класса. Как и в первом случае, не следует указывать .class
, так как это название класса, а не файла.
Вывод:
D:\Java>java -classpath ./bin src.BoxMachine
Box have size 4.085985295359718
Box have size 8.63682158248986
Box have size 6.027448124299726
Box have size 7.288317703877914
Box have size 1.106181659384694
Создание JAR-файлов
Чтобы программу было легко переносить и запускать, можно собрать скомпилированные классы в jar-файл — архив классов. Главное отличие от zip или rar-архивов — наличие файла манифеста. В этом манифесте указывается главный класс, который будет запускаться при выполнении jar-файла, classpath, а также много дополнительной информации. В главном каталоге создадим файл manifest.mf. Его содержимое будет следующим:
main-class: src.BoxMachine
class-path: bin/
main-class
указывает класс, который содержит метод main
и будет выполнен при запуске.
class-path
— путь к скомпилированным классам или дополнительным библиотекам.
Настало время собрать настоящую программу без IDE с помощью команды jar:
jar -cmf manifest.mf box-machine.jar -C bin .
-cmf
— флаг, после которого следует указать путь к файлу манифеста.
manifest.mf
— путь к манифесту.
box-machine.jar
— название выходного jar-файла.
-С
— флаг, после которого указывается путь к скомпилированным классам.
.
— путь, куда будет помещен jar-файл. В нашем случае —это главный каталог.
Теперь можно запустить. Запуск jar-файлов выполняется также с помощью команды java, но следом нужно указать флаг -jar
: он говорит о том, что запускается Jar-файл, а второй аргумент — путь к jar
-файлу, включая расширение:
java -jar box-machine.jar
Вывод:
Box have size 5.5495235762547965
Box have size 9.695870044165662
Box have size 2.3408385788129227
Box have size 7.2790741216674135
Box have size 2.3620854470160513
Компиляция в Java без IDE: обзор систем сборок
Несмотря на относительную простоту использования командной строки, с ее помощью очень сложно собирать средние и большие проекты. Это занимает много времени и чревато ошибками разной степени. К счастью, есть системы сборки, которые в разы облегчают процесс работы. Несколькими командами эта система может собрать проект любой сложности, а обилие плагинов, созданных за время существования таких систем, может избавить практически от любой головной боли.Как скомпилировать Java?
Самые известные системы сборки на Java — это Ant, Maven и Gradle. Среди нет плохой или хорошей: каждая из них создана для решения определенных задач. Рассмотрим каждую из них подробнее.Ant
Ant — инструмент сборки, который использует сценарий, описанный с помощью xml-файла. Структура xml-файла:
<?xml version="1.0"?>
<project name="имяПроекта" default="сценарийПоУмолчанию">
<target name="имяСценария">
// Действия сценария
<echo>Hello, World!</echo>
</target>
// Второй сценарий
// И тд
</project>
Создадим в главном каталоге файл build.xml со следующим содержимым:
<?xml version="1.0"?>
<project name="BoxMachine" default="test">
<target name="test">
<echo>First build in Ant!</echo>
</target>
</project>
В этом же каталоге вызовем команду ant:
D:\Java>D:\Temp\ant\bin\ant
Buildfile: D:\Java\build.xml
test:
[echo] First build in Ant!
BUILD SUCCESSFUL
Total time: 0 seconds
В теге <target>
можно указывать различные задания, позволяющие управлять сборкой и файловой системой. У Ant есть более 150 доступных команд, которые указаны в документации. В примере ниже используем только 5:
mkdir — создание директорий delete
— удаление файлов и директорийjavac
— компиляция Java–кодаjava
— запуск скомпилированного кода
<?xml version="1.0"?>
<project name="BoxMachine" default="compile">
<target name="compile">
<mkdir dir="result/classes"/>
<javac destdir="result/classes" includeantruntime="false">
<src path="src"/>
</javac>
</target>
<target name="run" depends="compile">
<java classname="BoxMachine" classpath="result/classes"/>
</target>
<target name="clean">
<delete dir="result"/>
</target>
</project>
В сценарии описано три действия — compile
, ,code>run и clean
.
compile
создает директорию result, в ней classes, затем с помощью javac компилирует классы в созданную директорию.
run
запускает скомпилированные классы командой java.
clean
удаляет директорию result.
Если в главном каталоге выполнить команду ant без аргументов, запустится действие compile. Если нужно выполнить определенное действие, его указывают в аргументе.
D:\Java>D:/Temp/ant/bin/ant compile
Buildfile: D:\Java\build.xml
compile:
[mkdir] Created dir: D:\Java\result\classes
[javac] Compiling 2 source files to D:\Java\result\classes
BUILD SUCCESSFUL
Total time: 1 second
Maven
Maven предлагает несколько другой подход к сборке проектов. Здесь разработчик скорее описывает свой проект и дополнительные инструменты, которые использует, в отличие от Ant, где сборка — это последовательность действий. Maven популярен среди разработчиков благодаря простому управлению зависимостями и удобной интеграции со всеми средами разработки. При работе с Maven придерживаются такой структуры проекта: Правила сборки, зависимости и прочее описывается в файле pom.xml. Как правило он находится в главной папке проекта. При запуске Maven проверяет структуру и синтаксис файла, предупреждая об ошибках. В главной директории рядом с папками bin и src создаем файл pom.xml, внутрь добавляем:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>ru.javarush.testmaven</groupId>
<artifactId>testMavenWithoutIde</artifactId>
<version>1.0.0</version>
<build>
<defaultGoal>compile</defaultGoal>
<sourceDirectory>src</sourceDirectory>
<outputDirectory>bin</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
</build>
</project>
Далее в командной строке выполняем команду mvn:
D:\Java>mvn
[INFO] Scanning for projects...
[INFO]
[INFO] -------------< ru.javarush.testmaven:testMavenWithoutIde >--------------
[INFO] Building testMavenWithoutIde 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ testMavenWithoutIde ---
[WARNING] Using platform encoding (Cp1251 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\Java\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ testMavenWithoutIde ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding Cp1251, i.e. build is platform dependent!
[INFO] Compiling 2 source files to D:\Java\bin
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 15.521 s
[INFO] Finished at: 2019-06-25T20:18:05+03:00
[INFO] ------------------------------------------------------------------------
Теперь в папке bin есть папка src, в которой находятся скомпилированные классы. В pom.xml в теге build определена цель сборки — компиляция, директории файлов исходного кода и результата компиляции, а также имя проекта.
У Maven есть множество целей сборки и плагинов для запуска тестирования, создания Jar-файлов, сборки дистрибутивов и других задач.
Gradle
Это самая молодая система сборки, которая основывается на Ant и Maven. Главное отличие — работа на базе ациклического графа для определения порядка выполнения задач. Это очень полезно при более сложных задачах, например, инкрементальных и многопроектных сборках. При сборке с помощью Gradle также рекомендуется придерживаться структуры папок проекта Maven. Кстати, файл для сборки в Gradle он называется build.gradle и выглядит гораздо меньше, чем у Maven. Пример для наших классов:
apply plugin: 'java'
apply plugin: 'application'
sourceSets {
main {
java {
srcDirs 'src'
}
}
}
sourceSets.main.output.classesDir = file("bin")
mainClassName = "src.BoxMachine"
defaultTasks 'compileJava', 'run'
В файле происходит подключение плагинов, определение директории файлов исходного кода (если не используется структура проектов Maven), директория результатов сборки, имя главного класса, а также задачи по умолчанию.
За запуск сборки отвечает команда gradle в директории, где лежит файл build.gradle:
d:\Java>D:\Temp\gradle\bin\gradle
Welcome to Gradle 5.4.1!
Here are the highlights of this release:
- Run builds with JDK12
- New API for Incremental Tasks
- Updates to native projects, including Swift 5 support
For more details see https://docs.gradle.org/5.4.1/release-notes.html
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :help
Welcome to Gradle 5.4.1.
To run a build, run gradle <task> ...
To see a list of available tasks, run gradle tasks
To see a list of command-line options, run gradle --help
To see more detail about a task, run gradle help --task <task>
For troubleshooting, visit https://help.gradle.org
BUILD SUCCESSFUL in 52s
1 actionable task: 1 executed
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
CHCP 1251
тоже иногда помогает справиться с "иероглифами" вместо кириллицы :)