Java запуск через bat

Java: компиляция в командной строке #3

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

  1. Один проект — одна директория. Чтобы не было путаницы, называть её стоит так же, как проект.
  2. В этой директории две папки: src и bin (или source/build(classes)) — как кому больше нравится.
  3. В этой же директории будут находиться и все остальные файлы, связанные с проектом (музыка, картинки, файл с описанием, какие-то библиотеки).

Куда интереснее рассмотреть проект побольше, к тому же работающий.
2. Проект CrazyTetris.java, лежащий в пакете md.leonis.tetris:

Так как этот проект не маленький, использует графику и музыку, а так же имеет зависимость от сторонних библиотек, вот ещё некоторые пути:

C:\Java\lib\. — тут подключаемые библиотеки
C:\Java\resources\. — графика и музыка
C:\Java\readme.txt — файл с описанием
C:\Java\manifest.mf — файл манифеста

Дерево каталогов для наглядности:

Исходный код проекта CrazyTetris:

При виде всего этого уже становится нехорошо, но в компании Sun о решении позаботились.

1. Компиляция.
Забегая вперёд скажу, что как и прежде, для компиляции я использую пакетные файлы. То есть, чтобы не писать гигантский код, я разнёс все данные по переменным.
Посмотрите сами, насколько громоздкими получаются команды:
Не дай Бог вводить всё это вручную каждый раз.

SET PROJECT=CrazyTetris
SET PACKAGE=md.leonis.tetris
SET FOLDER=md\leonis\tetris\ — это значение вычисляется автоматически
SET CLASSPATH=bin;lib\commons-logging-1.2.jar;lib\basicplayer3.0.jar;lib\mp3spi1.9.5.jar;lib\jl1.0.1.jar;lib\tritonus_share-0.3.6.jar
SET XLINT=-Xlint

Квадратные скобки означают, что оба набора параметров являются необязательными.

javac -classpath bin;lib\commons-logging-1.2.jar;lib\basicplayer3.0.jar;lib\mp3spi1.9.5.jar;lib\jl1.0.1.jar;lib\tritonus_share-0.3.6.jar -d bin -sourcepath src src\md\leonis\tetris\CrazyTetris.java 2>>errors.txt

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

Без этих библиотек команда заметно сокращается:

  • -classpath путь: здесь указываются пути до уже скомпилированных файлов. Пути можно указывать абсолютные (C:\Java\. ), а можно и относительные. Сюда же, через точку с запятой можно добавить подключаемые библиотеки.
    Для компиляции в этом проекте ключ -classpath вообще можно не указывать, но при запуске его забывать нельзя понадобится.
  • -d путь: папка, куда будут складироваться откомпилированные файлы проекта. В самом начале мы её определили: bin. Её необходимо создать заранее. Все остальные вложенные папки компилятор построит самостоятельно.
  • -sourcepath путь: это путь к исходным файлам проекта. В нашем случае src. Если в проекте только один файл, то этот ключ можно не указывать вообще. В нашем же случае, при отсутствии этого ключа компилятор упадёт с ошибкой:

«А если в проекте несколько файлов?» — Спросит внимательный читатель. И правда, исходных файлов может быть несколько. Компилятор в качестве разделителей понимает пробелы. Так же, можно использовать звёздочку, например *.java даст команду на компиляцию всех файлов. Но в этом отношении не стоит разгоняться, компилятор автоматически переведёт в байт-код все исходники, задействованные в программе.

2. Запуск программы.
Компилятор проверяет файлы с исходным кодом (*.java) и переводит их в байт-код. Его не запустить, подобно exe файлам. Зато файлы в формате байт-кода (class) могут исполняться в виртуальной машине Java, причём, одинаково хорошо на всех компьютерах и операционных системах, где эта машина установлена. Конечно, это утопия, одинаковый код в Windows, Linux, MAC OS, Solaris в любом случае потребует соблюдения правил, принятый в файловых системах этих операционок. Например, доступ к некоторым путям открыт не везде и не каждому. Так же внешний вид оконных приложений может отличаться. Таких мелочей много.

java [настройки] имяКласса [аргументы]
java [настройки] -jar имяФайла [аргументы]

Синтаксис с ключом -jar позволяет запускать на выполнение jar файлы.

Вместо java.exe можно использовать оконную версию javaw.exe. Впрочем, она ничего не выводит в командную строку, а в нашей ситуации это минус.

Тут уже без classpath не обойтись, как мы видим.
Обратите внимание на полное имя скомпилированного файла (класса): md.leonis.tetris.CrazyTetris
Это название пакета, потом через точку пишется имя файла без расширения.
Если добавим расширение — сразу же получим ошибку: Error: Could not find or load main class md.leonis.tetris.CrazyTetris.class
Хотя, эта ошибка очень распространённая, достаточно только написать не ту букву в пути.

2>>errors.txt в конце строки просит консольный вывод сохранять все найденные ошибки в файле errors.txt.
Если их мало, то все они умещаются на экране, а когда их сыпется несколько сотен — первые сообщения могут исчезнуть, как в случае Far Manager.

Для расширения кругозора можно этот ключик немного поменять.
Например, записывать не только ошибки, но и весь консольный вывод программы в файл log.txt. При этом используется дозапись данных:
>>log.txt 2>&1

Запись консольного вывода программы в файл log.txt. При этом, если этот файл уже есть, и он не пустой — вся информация в нём будет стёрта. Это достигается использованием одинарного знака «>»:
>log.txt

3. Создание JAR архива.
Если в программе всё устраивает — самое время заняться её публикацией. Разумно все классы разместить в одном архиве — легче передавать и меньше места.
Java и тут позволяет обойтись встроенные утилитами.
Тема создания jar файлов и манифестов очень обширная, не буду в одной теме забивать этим голову. Рассмотрим самый простой случай:

Ключ -cmf: это команда создать (c) jar файл (f) и внести в него данные из файла-манифеста (m). Последовательность тут очень важна. Другой вариант вызова:

После имени файла создаваемого архива в первом примере идёт название файла-манифеста, а следом всё то, что мы в него запакуем.
Нас интересует содержимое папки bin (без неё самой).

Можно было бы включить а архив музыку и картинки, но доставать их оттуда, особенно музыку, достаточно накладно.
Лучше держать их отдельно.

Немного по файлу-манифесту:
Без него Java не разберётся какой именно файл в архиве нужно запускать. И уж тем более, виртуальная машина не знает ни о каких зависимостях.

Содержимое файла manifest.mf:

Manifest-Version: 1.0
Created-By: 1.7.0_72 (Oracle Corporation)
Main-Class: md.leonis.tetris.CrazyTetris
Class-Path: lib/commons-logging-1.2.jar lib/basicplayer3.0.jar lib/mp3spi1.9.5.jar lib/jl1.0.1.jar lib/tritonus_share-0.3.6.jar

  • Manifest-Version: версия манифеста. Не меняем
  • Created-By: версия вашей JDK
  • Main-Class: полный путь к главному (исполняемому) файлу проекта
  • Class-Path: пути, по которым можно найти подключаемые библиотеки.

4. Создание zip архива.
А вот теперь соберём всё, что относится к проекту в одном архиве:

В этой команде архиватор 7z получает задание запаковать файлы, включая и содержимое поддиректорий в формат zip с максимальной степенью сжатия. Результирющий архив получит имя CrazyTetris.zip, и в него будут помещены файлы: CrazyTetris.jar, readme.txt, а так же содержимое папок resources и lib.

  • compile.bat: компиляция и запуск в случае успеха
  • run.bat: просто запуск на выполнение
  • jar.bat: создание jar архива
  • zip.bat: создание zip архива
chcp 1251 @REM Файл конфигурации для остальных пакетных файлов @REM Предполагается, что все пакетные файлы находятся в корневой папке проекта. @REM Исходный код программы должен находится в папке src. @REM Проект скомпилируется в папку bin. @REM Все найденные ошибки будут записаны в файл errors.txt @REM Путь к файлам java.exe, javac.exe, jar.exe: SET PATH=%PATH%;C:\Program Files\Java\jdk1.7.0_72\bin @REM Имя файла проекта. Пример: Test.java необходимо записать как Test SET PROJECT=CrazyTetris @REM Название пакета. Пример: ru.java.testutils @REM Полный путь из корневой папки проекта к файлу с исходным колом: @REM src/ru/java/testutils/Test.java @REM Если пакет не используется - после знака равенства ничего не указываем. SET PACKAGE=md.leonis.tetris @REM Подключаемые библиотеки добавляются через точку с запятой, без пробелов. @REM Пример: SET CLASSPATH=bin;lib\commons-logging-1.2.jar;lib\basicplayer3.0.jar;lib\mp3spi1.9.5.jar;lib\jl1.0.1.jar;lib\tritonus_share-0.3.6.jar @REM Обязательно нужно указывать путь к скомпилированному проекту - bin SET CLASSPATH=bin;lib\commons-logging-1.2.jar;lib\basicplayer3.0.jar;lib\mp3spi1.9.5.jar;lib\jl1.0.1.jar;lib\tritonus_share-0.3.6.jar @REM SET CLASSPATH=bin @REM Параметр Xlint компилятора SET XLINT= @REM SET XLINT=-Xlint ECHO OFF CLS
call _settings.bat SET FOLDER= IF NOT "%PACKAGE%"=="" SET FOLDER=%PACKAGE:.=\% IF NOT "%PACKAGE%"=="" SET PACKAGE=%PACKAGE%. IF NOT "%FOLDER%"=="" SET FOLDER=%FOLDER%\ IF NOT EXIST .\bin md .\bin IF EXIST .\bin\%FOLDER%*.class DEL .\bin\%FOLDER%*.class IF EXIST errors.txt DEL errors.txt ECHO Compiling project %PACKAGE%%PROJECT%. REM ******************** REM команд(ы) компиляции REM ******************** javac -classpath %CLASSPATH% -d bin -sourcepath src src\%FOLDER%%PROJECT%.java %XLINT% 2>>errors.txt ECHO. :wait IF NOT EXIST errors.txt GOTO wait FOR %%i IN (errors.txt) DO SET fsize=%%~zi IF NOT %fsize%==0 GOTO error ECHO Compiling succesful. Launching Java code. REM ********************************** REM запуск откомпилированной программы REM ********************************** java -classpath %CLASSPATH% %PACKAGE%%PROJECT% 2>>errors.txt FOR %%i IN (errors.txt) DO SET fsize=%%~zi IF NOT %fsize%==0 GOTO error IF EXIST errors.txt DEL errors.txt GOTO end :error ECHO The compiler found the following errors: ECHO ---------------------------------------- ECHO. TYPE errors.txt ECHO. PAUSE :end
call _settings.bat ECHO Launching Java code. IF EXIST errors.txt DEL errors.txt IF NOT "%PACKAGE%"=="" SET PACKAGE=%PACKAGE%. ECHO OFF REM ********************************** REM запуск откомпилированной программы REM ********************************** java -classpath %CLASSPATH% %PACKAGE%%PROJECT% 2>>errors.txt ECHO. FOR %%i IN (errors.txt) DO SET fsize=%%~zi IF NOT %fsize%==0 GOTO error IF EXIST errors.txt DEL errors.txt GOTO end :error ECHO JVM found the following errors: ECHO ------------------------------- ECHO. TYPE errors.txt ECHO. PAUSE :end
@REM Этот пакетный файл генерирует jar архив проекта call _settings.bat IF EXIST %PROJECT%.zip DEL %PROJECT%.zip IF EXIST %PROJECT%.jar DEL %PROJECT%.jar ECHO Creating JAR archive: %PROJECT%.jar @REM Генерация архива: jar.exe -cmf manifest.mf %PROJECT%.jar -C bin . @REM Проверка архива: java.exe -jar %PROJECT%.jar
@REM Этот пакетный файл пакует проект и все ресурсы в zip архив SET PATH=%PATH%;C:\Program Files\7-Zip call _settings.bat IF EXIST %PROJECT%.zip DEL %PROJECT%.zip IF NOT EXIST %PROJECT%.jar GOTO exit ECHO Creating ZIP archive: %PROJECT%.zip @REM Генерация архива: 7z.exe a -r -tzip -mx9 %PROJECT%.zip %PROJECT%.jar readme.txt resources lib :exit

У этого подхода есть недостаток — привязка в Windows. Альтернативы:
ANT >>>
MAVEN >>>

Комментарии

Leonis, советую посмотреть в сторону Ant. Отличный сборщик. Конфиг прописал в xml для каждого проекта и собирай на счастье. Сам сначала собирал батником, потом задолбало. Перешел на Ant. В итоге компилировал, собирал, подписывал jar’ки и запускал тесты быстро и удобно.

Это всё прелюдия к «муравью». Он у меня уже скачан, установлен и только усталость не позволяет перевести проекты на его рельсы прямо сейчас. К тому же, на этих примерах укажу недостатки, они не идеальны, например, в плане переносимости в Linux — эти пакетные файлы работать как надо не будут. Ant это универсальный сборщик, не зависящий от платформы и используемых IDE.

Источник

Читайте также:  Velocity templates in java
Оцените статью