Running java from console

Running java from console

В прошлой публикации мы установили и настроили Sublime Text в качестве редактора для написания кода на Java.

  • о компиляции и запуске Java-программ из консоли
  • как выводить в нее корректный русский текст
  • способ отображения байт-кода

На первых порах начинающему программисту очень важно научиться выполнять необходимые действия минимальными средствами, чтобы:

  • иметь представление, что происходит «под капотом»
  • не быть зависимым от среды разработки
  • не превратиться в специалиста по нажиманию кнопок в инструментах для профессионалов
  • не оказаться беспомощным за их пределами

Вам сейчас нужно максимально набить шишек, находясь в спартанских условиях, которые закалят и научат самостоятельно и оперативно решать возникающие проблемы. Это придаст уверенности и повысит вашу экспертность.

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

Компилировать и запускать программы на первых порах мы будем из консоли. В этой и последующих статьях мы будем много работать с этим инструментом. Это важный навык, который используется программистами повсеместно.

Откроем в Sublime Text терминал, нажав Ctrl + Alt + T (при этом файл MyFirstApp.java должен быть открыт в редакторе). Обязательно проверьте, что терминал запустился в папке StartJava (или где вы сохранили класс).

Для компиляции воспользуемся уже знакомой утилитой javac (java compiler, компилятор java). Она нужна для преобразования Java-кода в язык виртуальной машины (байт-код).

Отсутствие каких-либо сообщений свидетельствует о том, что компилятор не нашел ошибок в нашем коде. Результатом его работы стал файл MyFirstApp.class.

Как мы уже знаем, MyFirstApp.class содержит байт-код. Для его исполнения воспользуемся утилитой java. Именно она стартует JVM, которая, в свою очередь, запустит класс MyFirstApp.

Обратите внимание, что необходимо указать не имя файла MyFirstApp.class, а имя класса. При этом писать какое-либо расширение не нужно. Утилита java принимает в качестве параметра именно имя класса, а не имя файла, где он находится.

Мы уже не первый раз упоминаем про байт-код, но до сих пор в глаза его не видели. Исправим эту ситуацию.

Для отображения (декомпиляции) байт-кода класса необходимо в консоли написать команду javap -c MyFirstApp:

Как правило, умение читать и понимать байт-код, вносить в него изменения для рядовых Java-разработчиков обычно не требуется — это очень специфические знания. Так что долго не сидите на этой теме.

Если обобщить все этапы, которые проходит программа перед запуском, то схематично их можно отобразить в виде схемы:

Чтобы посмотреть, как работает программа, необходимо выполнить два действия: компиляцию и запуск. Если эти шаги требуется исполнять часто, то данный процесс рано или поздно надоест. Хотелось бы его упростить.

Удалите из папки class-файл, чтобы все было честно. И запустите программу без компиляции в явном виде, написав java MyFirstApp.java:

Мы только что запустили (и скомпилировали) файл с java-кодом без использования команды javac. При этом исходный код, в любом случае, компилируется в памяти (без создания на диске class-файла), а затем исполняется JVM.

Эта функция ограничена кодом, который хранится в одном файле. Она не сработает для программ, состоящих из двух и более файлов.

Теперь, когда вы умеете компилировать и запускать программу, можете поэкспериментировать с кодом MyFirstApp.java, внося в него изменения. Попробуем удалить точку с запятой.

 > java MyFirstApp.java error: 'main' method is not declared 'public static' 

Если вы используете Linux или macOS, то дальше можете не читать, т. к. ниже описаны проблемы и их решения для Windows. У вас таких проблем не будет!

Написанная нами программа выводит текст в консоли на английском языке. Как вы думаете, что произойдет, если попробовать вывести текст на русском?

 > java MyFirstApp.java Р?апиС?Р°Р?Р? Р?Р?Р?Р°Р?Р?С?, С?Р°Р?Р?С?Р°Р?С? Р?Р?Р·Р?Р? 

Что-то пошло не так и вместо русского текста отобразились какие-то закорючки. В чем тут причина и как эту ситуацию можно исправить?

Первое, что приходит в голову — это какая-то проблема с кодировкой. Нужно разобраться, в какой момент она возникает.

Посмотрим, какая кодировка у файла с нашим кодом. Она отображается в правом нижнем углу окна. Видим, что это UTF-8.

А какая кодировка используется в OC? Определить это можно разными путями. Например, в Windows в реестре (для его запуска из консоли используйте команду regedit) по следующему адресу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage можно посмотреть, чему равен параметр под названием ACP (ANSI code page).

У меня он имеет значение 1251. Это стандартная кодировка для русских версий Windows. У вас она может быть другой — все зависит от языка (кодировки) системы.

Есть еще один способ узнать кодировку, который подходит для любой ОС — это воспользоваться Java, поместив в наш класс две новых строки:

 import java.nio.charset.Charset; public class MyFirstApp < public static void main(String[] args) < System.out.println(Charset.defaultCharset().displayName()); >> 

Вникать в то, что означает этот код мы не будем — наша задача лишь получить универсальным способом значение кодировки. Но если в двух словах, то в первой строке мы подключаем класс Charset, а в пятой выводим на экран значение кодировки по умолчанию для ОС, воспользовавшись возможностями данного класса.

 > java MyFirstApp.java windows-1251 
 > chcp Текущая кодовая страница: 866 

Она выдала 866. Это же число можно наблюдать и в реестре у параметра OEMCP (Original equipment manufacturer code page). Это DOS-кодировка, которая досталась нам в наследство.

Не удивительно, что Java не смогла корректно отобразить кириллический текст, когда используется столько кодировок в одной ОС.

Дело в том, что во время компиляции компилятор определяет кодировку исходного кода, опираясь на значение кодировки по умолчанию (на кодировку вашей ОС), а не на кодировку файла. В разных системах используются разные кодировки по умолчанию: в Windows — windows-1251, в Linux и Mac — UTF-8.

В Windows, ко всему прочему, еще и кодировка консоли не совпадает с кодировкой системы! Консоль по историческим причинам имеет кодировку Cp866 (видимо, в целях совместимости).

Затем JVM определяет кодировку по умолчанию во время запуска, используя системное свойство file.encoding. Значение для этого свойства устанавливается Java-машиной один раз при старте на основании данных, взятых из ОС.

Кодировка, используемая при выводе в консоль тоже системная, а не консоли. Если они не совпадают, то не видать нам корректного вывода кириллицы.

В итоге кодировку надо учитывать во время компиляции, во время запуска и во время вывода текста на консоль, например, при вводе с клавиатуры. Невыполнение этого правила в любом из этих мест способно вызвать проблемы.

У компилятора есть опция -encoding. Она позволяет принудительно указать кодировку исходника, чтобы компилятор не определял ее, опираясь на кодировку системы. Как вы помните, файл имеет кодировку UTF-8. Вот ее мы и укажем: javac -encoding utf8 MyFirstApp.java.

Если для однофайловых программы вы решили не использовать явно компиляцию, а сразу писать java, то для переопределения системного свойства file.encoding существует специальная команда. Вместе с ней запуск программы будет выглядеть так:

 > java -Dfile.encoding=UTF8 MyFirstApp.java Написано однажды, работает везде 

-Dfile.encoding — это уже параметр JVM, с помощью которого мы устанавливаем принудительно нужное нам значение, сохраняя его в file.encoding.

От всех этих параметров и правил может закружиться голова. И все эти годы Java-разработчики жили и мучились с кодировками и ошибками, которые они вызывали в программах.

Но не прошло и 25 лет, как появилась хорошая новость. Начиная с Java 18, значение кодировки по умолчанию определяется не исходя из кодировки ОС, а исходя из того, что она является UTF-8 — отныне это кодировка по умолчанию. Никакие параметры больше не нужны. Убедимся в этом:

 > "C:\Program Files\java\SapMachine-18\bin\java.exe" MyFirstApp.java Написано однажды, работает везде > "C:\Program Files\java\SapMachine-18\bin\javac.exe" MyFirstApp.java > "C:\Program Files\java\SapMachine-18\bin\java.exe" MyFirstApp Написано однажды, работает везде 

Для тех, кто использует Java меньше 18, придется использовать все параметры, указанные ранее — ни куда от них не деться. Но и тут есть выход.

Утомительно все время указывать кодировку. Этот вопрос можно решить, используя JAVA_TOOL_OPTIONS со значением -Dfile.encoding=UTF8. Необходимо установить эту переменную и ее значение в качестве переменной среды (ранее мы уже имели дело с другой переменной — JAVA_HOME). Не забудьте перезапустить консоль.

Благодаря этой переменной кодировка будет устанавливаться автоматически при каждом запуске JVM. При этом в консоли будет отображаться сообщение:

 Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 
 > java MyFirstApp.java Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 Написано однажды, работает везде > javac MyFirstApp.java Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 > java MyFirstApp Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 Написано однажды, работает везде 

Забежим немного вперед и рассмотрим ситуацию, когда нам нужно ввести с клавиатуры что-то на русском языке. Да, ввод мы еще не проходили, но мне совсем не хочется размазывать эту информацию по разным статьям. Пусть все, что связано с компиляцией и запуском, с кодировками, их проблемы и решения будет в одном месте.

Добавим в наш код библиотечный класс Scanner, который позволит считывать, введенные с клавиатуры символы, и пару строк с его использованием:

 import java.util.Scanner; public class MyFirstApp < public static void main(String[] args) < System.out.println("Написано однажды, работает везде"); Scanner console = new Scanner(System.in); System.out.print("Введите свое имя: "); System.out.println(console.nextLine()); >> 
 > java MyFirstApp.java Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 Написано однажды, работает везде Введите свое имя: Максим . 
 замените Scanner console = new Scanner(System.in); на Scanner console = new Scanner(System.in, "cp866"); 
 > java MyFirstApp.java Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 Написано однажды, работает везде Введите свое имя: МАКСИМ ШШШШ ИИИИ МАКСИМ ШШШШ ИИИИ 

Если после всего проделанного, что я описал выше, у вас вместо русского текста выводится пустая строка, то необходимо в консоли ввести chcp 866 и заново запустить программу.

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

Если не использовать в коде программы или во время ввода с клавиатуры русский язык, то никаких проблем с кодировками не возникнет. Но, если вы все же ступили на путь использования кириллических символов, то вам придется проделать все те настройки, которые были описаны во второй половине статьи. Таких проблем в профессиональных средах разработки практически не бывает, т. к. они умеют правильно отображать текст в консоли, делая автоматически, если нужно, его перекодировку.

Источник

Читайте также:  What is java swing gui
Оцените статью