Статьи

Компиляция и запуск Java без IDE

Недавний поток Java subreddit под названием « Компиляция пакетов Java без IDE » поставил вопрос: «Есть ли [там] команда, которая собирает группу java-файлов, которые находятся внутри пакета, в отдельную папку (давайте просто назовем это bin), и как я пойду о запуске новых файлов классов? » Автор поста, kylolink , объясняет, что «когда я начал использовать Java, я полагался на Eclipse, чтобы выполнить всю компиляцию для меня, и просто беспокоился о написании кода». Я неоднократно сталкивался с этой проблемой, и, собственно, именно это побудило мою (сейчас 4 года) публикацию в блоге системы GPS и IDE: полезно или вредно? Мне нравятся мощные современные Java IDE, и они ежедневно облегчают мою жизнь, но есть преимущества в том, чтобы знать, как создавать и запускать простые примеры Java без них. Этот пост посвящен тому, как это сделать.

В своем блоге « Изучение Java с помощью простых тестов» я писал о том, как иногда мне нравится использовать простой текстовый редактор и инструменты командной строки для написания, создания и запуска простых приложений. Теперь у меня есть довольно хорошее представление о том, сколько требуют мои «накладные расходы» для моих любимых Java IDE, и я принимаю решение о том, достаточны ли преимущества, достигнутые от использования IDE, чтобы оправдать «накладные расходы». В большинстве реальных приложений нет сомнений, что накладные расходы IDE того стоят. Однако для самых простых примеров приложений это не всегда так. Остальная часть этого поста показывает, как создавать и запускать код Java без IDE для этих ситуаций.

Код Java, который будет построен и выполнен

Чтобы сделать обсуждение этого поста более конкретным, я буду использовать некоторые очень простые классы Java, которые связаны друг с другом посредством композиции или наследования и находятся в одном и том же именованном пакете (не в неназванном пакете ), называемом dustin.examples . Два из классов не имеют main функций, а третий класс Main.java имеет main функцию, позволяющую продемонстрировать запуск класса без IDE. Список кодов для трех классов показан ниже.

Parent.java

01
02
03
04
05
06
07
08
09
10
package dustin.examples;
 
public class Parent
{
   @Override
   public String toString()
   {
      return "I'm the Parent.";
   }
}

Child.java

01
02
03
04
05
06
07
08
09
10
package dustin.examples;
 
public class Child extends Parent
{
   @Override
   public String toString()
   {
      return "I'm the Child.";
   }
}

Main.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
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:\java\examples\javacAndJava\ , мне нужно иметь что-то подобное в моей команде: javac -sourcepath src src\dustin\examples\*.java . Следующий снимок экрана показывает результаты этого.

javacCompilingPackageDirectoryButToSameDirForClasses

Поскольку мы не указали каталог назначения для файлов .class , по умолчанию они были помещены в тот же каталог, что и исходные файлы .java из которых они были скомпилированы. Мы можем использовать опцию -d чтобы исправить эту ситуацию. Наша команда может быть выполнена сейчас, например, как javac -sourcepath src -d classes src\dustin\examples\*.java . Как указано ранее, указанный целевой каталог ( classes ) уже должен существовать. Когда это произойдет, команда поместит файлы .class в назначенный каталог, как показано на следующем снимке экрана.

javacDoptionPlacesClassesCorrectDir

С исходными файлами 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 .

javaRunningSimpleExamplesParentChildMain

Сборка и бег с муравьем

Для простейших приложений Java довольно просто использовать javac и java для сборки и выполнения приложения соответственно, как только что продемонстрировано. Поскольку приложения становятся немного более вовлеченными (например, код, существующий в более чем одном пакете / каталоге, или более сложные зависимости пути к классам от сторонних библиотек и сред), этот подход может стать громоздким. Apache Ant является старейшим из «большой тройки» инструментов сборки Java и используется в тысячах приложений и развертываний. Как я уже говорил в предыдущем посте в блоге , очень просто создать очень простой файл сборки Ant, особенно если он начинается с шаблона, который я описал в этом посте .

Следующий листинг кода предназначен для файла Ant build.xml который можно использовать для компиляции файлов .java файлы .class а затем запустить класс dustin.examples.Main как это было сделано выше для javac и java .

build.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<project name="BuildingSansIDE" default="run" basedir=".">
   <description>Building Simple Java Applications Without An IDE</description>
 
   <target name="compile"
           description="Compile the Java code.">
      <javac srcdir="src"
             destdir="classes"
             debug="true"
      includeantruntime="false" />
   </target>
 
   <target name="run" depends="compile"
           description="Run the Java application.">
      <java classname="dustin.examples.Main" fork="true">
         <classpath>
           <pathelement path="classes"/>
         </classpath>
      </java>
   </target>
</project>

Я не использовал свойства Ant и не включал общие цели, которые я обычно включаю (такие как «clean» и «javadoc»), чтобы сделать этот пример максимально простым и приблизить его к предыдущему примеру с использованием javac и java . Также обратите внимание, что я включил «debug», установленный в «true» для задачи Ant javac, потому что это не так в Ant по умолчанию, но верно в javac по умолчанию. Не удивительно, что задача Ant javac и задача java очень похожи на командные инструменты javac и java .

Потому что я использовал имя по умолчанию, которое Ant ожидает для файла сборки, когда оно не указано явно ( build.xml ), и потому что я предоставил цель «run» в качестве «по умолчанию» для этого файла сборки и потому что я включил «compile» в качестве зависимости чтобы запустить цель «run» и поскольку Ant находился в пути моей среды, все, что мне нужно сделать в командной строке, чтобы заставить Ant скомпилировать и запустить пример, это набрать «ant» в каталоге с файлом build.xml . Это продемонстрировано на следующем снимке экрана.

antCompilingAndRunningSimpleJavaApp

Хотя я продемонстрировал компиляцию и запуск простого Java-приложения с помощью Ant, обычно я компилирую только с Ant и запускаю с использованием java (или сценария, который вызывает java если путь к классам отвратителен).

Сборка и бег с Maven

Хотя Ant был первым распространенным средством сборки Java, Apache Maven в конечном итоге приобрел свою значимость благодаря большей части принятия соглашения и поддержки общих репозиториев библиотек. Maven проще всего использовать, когда код и сгенерированные объекты соответствуют его стандартной структуре каталогов . К сожалению, мой пример не соответствует этой структуре каталогов, но Maven позволяет переопределить ожидаемую структуру каталогов по умолчанию . Следующий листинг кода предназначен для POM-файла Maven, который переопределяет исходный и целевой каталоги и предоставляет другие минимально необходимые элементы для сборки Maven с использованием Maven 3.2.1 .

pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
<project>
   <modelVersion>4.0.0</modelVersion>
   <groupId>dustin.examples</groupId>
   <artifactId>CompilingAndRunningWithoutIDE</artifactId>
   <version>1</version>
 
   <build>
      <defaultGoal>compile</defaultGoal>
      <sourceDirectory>src</sourceDirectory>
      <outputDirectory>classes</outputDirectory>
      <finalName>${project.artifactId}-${project.version}</finalName>
   </build>
</project>

Поскольку в приведенном выше файле pom.xml указано значение «defaultGoal» для «compile», а также потому, что pom.xml — это пользовательский POM-файл по умолчанию, который ищет исполняемый файл Maven (mvn), а также потому, что каталог bin установки Maven находится на моем пути, я только необходимо запустить «mvn» для компиляции файлов .class как показано на следующем снимке экрана.

mavenCompilingJavaCode

Я также могу запустить скомпилированное приложение с Maven, используя команду mvn exec:java -Dexec.mainClass=dustin.examples.Main , что продемонстрировано на следующем снимке экрана.

mavenRunningSimpleApp

Как и в случае с Ant, я бы обычно не использовал Maven для запуска моего простого Java-приложения, а вместо этого использовал бы java для скомпилированного кода (или использовал бы скрипт, который вызывает java напрямую для длинных путей к классам).

Сборка и запуск с Gradle

Gradle — самый молодой, модный и модный из трех основных инструментов сборки Java. Иногда я скептически отношусь к существу чего-то модного, но я нашел много вещей, которые нравятся в Gradle (написано на Groovy вместо XML, встроенная поддержка Ant, встроенная поддержка Ivy, конфигурация по соглашению, которая легко переопределяется Поддержка репозитория Maven и т. Д.). В следующем примере показан файл сборки Gradle, который можно использовать для компиляции и запуска простого приложения, являющегося основным примером кода для этого поста. Это адаптировано из примера, который я представил в посте блога Simple Gradle Java Plugin Customization .

build.gradle

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
apply plugin: 'java'
apply plugin: 'application'
 
// Redefine where Gradle should expect Java source files (*.java)
sourceSets {
    main {
        java {
            srcDirs 'src'
        }
    }
}
 
// Redefine where .class files are written
sourceSets.main.output.classesDir = file("classes")
 
// Specify main class to be executed
mainClassName = "dustin.examples.Main"
 
defaultTasks 'compileJava', 'run'

Первые две строки файла build.gradle определяют приложение плагина Java и плагина Application , автоматически build.gradle в эту сборку множество функций. Определение «sourceSets» и «sourceSets.main.output.classesDir» позволяет переопределять стандартные каталоги плагина Java Gradle для исходного кода Java и скомпилированных двоичных классов соответственно. «MainClassName» позволяет явно указать, какой класс должен запускаться как часть плагина приложения. Строка «defaultTasks» определяет задачи, которые нужно выполнить, просто набрав «gradle» в командной строке: «compileJava» — это стандартная задача, предоставляемая плагином Java, а «run» — стандартная задача, предоставляемая плагином Application. Поскольку я назвал файл сборки build.gradle и потому что я определил задачи по умолчанию ‘compileJava’ и ‘run’ и поскольку у меня есть каталог bin установки Gradle в моем пути, все, что мне нужно было сделать для сборки и запуска примеров, это введите «gradle», и это продемонстрировано на следующем снимке экрана.

gradleBuildAndRunSimpleExampleJavacJava

Даже самый большой скептик должен признать, что сборка Gradle довольно проста для этого простого примера. Он сочетает в себе краткость, основанную на определенных соглашениях и допущениях, с очень простым механизмом переопределения выбранных значений по умолчанию при необходимости. Тот факт, что он в Groovy, а не в XML, также очень привлекателен!

Как и в случае с Ant и Maven, я, как правило, собираю только эти инструменты и обычно запускаю скомпилированные .class напрямую с помощью java или сценария, который вызывает java . Кстати, я обычно также архивирую эти .class в JAR для запуска, но это выходит за рамки этого поста.

Вывод

В среде IDE часто нет необходимости создавать простые приложения и примеры, и она может даже оказаться более затратной, чем это стоит для простейших примеров. В таком случае довольно просто применить javac и java напрямую для построения и запуска примеров. По мере того как примеры становятся все более сложными, инструмент для сборки, такой как Ant, Maven или Gradle, становится все более привлекательным. Тот факт, что многие IDE поддерживают эти инструменты сборки, означает, что разработчик мог перейти к IDE с помощью инструмента сборки, созданного ранее в процессе, если было определено, что поддержка IDE необходима, поскольку простое приложение превратилось в полноценный проект.

Ссылка: Компиляция и запуск Java без IDE от нашего партнера по JCG Дастина Маркса в блоге Inspired by Actual Events .