какая команда используется для запуска процесса компиляции исходного файла в байт код
Компиляция файлов Java *.class с помощью javac
Узнайте, как использовать javac для создания файлов *.class.
1. Обзор
В этом руководстве будет представлен инструмент javac и описано, как использовать его для компиляции исходных файлов Java в файлы классов.
2. Команда javac
Мы можем указать параметры и исходные файлы при выполнении инструмента javac :
Где [параметры] обозначает параметры, управляющие операциями инструмента, и [исходные файлы] указывает один или несколько исходных файлов, которые будут скомпилированы.
Параметры javac подразделяются на три группы: стандартные, кросс-компиляционные и дополнительные. В этой статье мы сосредоточимся на стандартных и дополнительных опциях.
Параметры кросс-компиляции используются для менее распространенного случая компиляции определений типов в реализации JVM, отличной от среды компилятора, и не будут рассматриваться.
3. Определение типа
Давайте начнем с представления класса, который мы собираемся использовать для демонстрации опций javac :
Обратите внимание, что в этой статье мы используем разделители файлов *unix; на компьютерах с Windows мы должны использовать обратную косую черту (‘ \’ ) вместо прямой косой черты (‘ /’ ).
4. Стандартные опции
Давайте выполним следующую команду в каталоге, содержащем структуру, представленную в предыдущем разделе:
Вот несколько других часто используемых вариантов:
Предположим, что у нас есть два файла с именами options и types в каталоге javac-args со следующим содержимым:
Предположим, что в каталоге javac-args есть файл с именем arguments :
5. Дополнительные опции
Вот некоторые из самых удобных -Xlint клавиш:
Теперь создайте файл с именем xl в tops в каталоге javac-args со следующим содержимым:
При выполнении этой команды:
мы должны увидеть rawtypes и непроверенные предупреждения:
6. Заключение
Какая команда используется для запуска процесса компиляции исходного файла в байт код
В других языках, например, C++, этап компиляции в байт-код отсутствует: компилятор сразу преобразует текст программы (код) в машинный код и создает бинарный файл для исполнения (в Windows – это файл с расширением exe). Основным недостатком данного подхода является зависимость от операционной системы и процессора: для каждой операционной системы и процессора необходимо скомпилировать свою версию машинного кода.
Для того, чтобы скомпилировать и запустить программу на языке Java, необходимо выполнить следующий перечень действий:
1) создать файл с расширением java, содержащий текст программы;
2) скомпилировать его с помощью компилятора javac. Компилятор проверит код на ошибки и, если он корректен, выдаст файл с расширением class;
3) полученный файл, содержащий байт-код, запустить с помощью виртуальной машины Java.
Компилятор javac в Windows
Перейдем в командную строку Windows (cmd) и введем команду «javac».
В результате Вы можете наблюдать следующее сообщение: «»javac» не является внутренней или внешней командой, исполняемой программой или пакетным файлом». Также Вы можете ввести команду «java» и увидеть аналогичное сообщение: «»java» не является внутренней или внешней командой, исполняемой программой или пакетным файлом». Для исправления этой ситуации необходимо выполнить следующие действия:
1) Перейти по пути « C:\Program Files\Java\jdk-10.0.2\bin » (если Вы оставили путь для установки JDK по умолчанию, как это было в предыдущем уроке). В этой папке Вы можете наблюдать исполняемые файлы java.exe и javac.exe.
2) Переходим в окно Windows «Этот компьютер». На свободном пространстве нажимаем правой кнопкой мыши, должно появиться контекстное меню. В нём выбираем пункт «Свойства».
3) В появившемся окне «Система» нажимаем на «Изменить параметры».
4) В появившемся окне «Свойства системы» во вкладке «Дополнительно» нажимаем на кнопку «Переменные среды…».
5) В появившемся окне «Переменные среды» во вкладке «Системные переменные» находим переменную «Path» и нажимаем на кнопку «Изменить…».
6) В появившемся окне «Изменить переменную среды», нажимаем на кнопку «Создать» и добавляем новое значение: « C:\Program Files\Java\jdk-10.0.2\bin\ ». Принимаем изменения и нажимаем кнопку «ОК».
7) Принимаем изменения во всех остальных открытых нами окнах, нажимая кнопку «ОК».
8) Переходим в командную строку и вводим «javac» или «java».
Система выдаст нам справку, в которой показано как использовать (usage) команду и перечислены её возможные опции (options). Source files (дословно «источники файлов») – это пути к компилируемым нами файлам.
Компиляция программы и её запуск на исполнение
Скомпилируем нашу первую программу и запустим её.
Создадим файл Cat.java (Помните же, что имя класса должно соответствовать имени файла?) и поместим в этот файл следующий код:
public class Cat <
public static void main(String[] args) <
System.out.println(«Привет, я кот! Твой друг ;)»);
>
>
В командной строке введём команду «javac» и через пробел укажем путь к созданному файлу. Так, если Вы создали файл Cat.java на рабочем столе Windows, то путь к файлу будет следующим: « C:\Users\ USERNAME \Desktop\Cat.java », где USERNAME – имя Вашего пользователя.
Иногда могут возникать сложности при создании файла с расширением java: используя стандартный текстовый блокнот в Windows, новички просто изменяют имя файла, и в итоге вместо файла Cat.java создается файл Cat.java.txt. Для создания файла именно с расширением java, можно воспользоваться каким-нибудь текстовым редактором, например, Notepad++. Будьте внимательны!
В процессе компиляции исходного кода каждый отдельный класс помещается в собственный выходной файл, называемый по имени класса и получающий расширение class. Его содержимое можно открыть также текстовым редактором, например, Notepad++.
Чтобы выполнить программу, следует воспользоваться загрузчиком приложений java. При запуске необходимо указать имя класса, который нужно выполнить. Загрузчик приложений java автоматически будет искать файл с указанным именем и расширением class. И если он найдет такой файл, то выполнит код, содержащийся в указанном классе.
Введём в командной строке «java Cat» и получим ошибку «Не могу найти или загрузить основной класс Cat»:
Error: Could not find or load main class Cat
Caused by: java.lang.ClassNotFoundException: Cat
Введём в командной строке теперь верную команду: « java –classpath C:\Users\ USERNAME \Desktop Cat ». Здесь мы использовали опцию classpath («путь к файлу с расширением class»). Для изучения схемы использования команды и возможных опций, как Вы уже догадались, необходимо ввести команду «java».
В командной строке должно появиться сообщение: «Ваша первая программа на Java». Если Вы видите кракозябры, Вам необходимо изменить кодировку командной строки. Это делается командой chcp в формате: « chcp ». Чтобы изменить кодировку в командной строке на UTF-8, необходимо выполнить команду: « chcp 65001 ».
Скомпилируйте и запустите программу для класса Dog. В выводимое сообщение на экран внесите соответствующие изменения.
В следующем уроке мы установим интегрированную среду разработки, создадим первый проект и запустим нашу программу.
Компиляция java кода из командной строки
Сегодня я расскажу как устроен базовый проект Java, как компилируется код и как выполнить готовую программу.
Java Source и каталоги классов
Простой Java-проект содержит один каталог, внутри которого хранятся все исходные файлы. Файлы обычно хранятся не внутри исходного каталога, а в подкаталогах, соответствующих их структуре пакета. Пакеты – это просто способ сгруппировать исходные файлы, которые принадлежат друг другу. Исходный каталог часто называют src, но это не является обязательным требованием.
Например, если вы используете инструмент сборки Maven, вы, как правило, будете использовать другую структуру каталогов, где исходный код Java хранится в каталоге src/main/java(в корневом каталоге вашего проекта).
Этот каталог часто называют классами, но, опять же, он не является обязательным, и он зависит от того, какой инструмент сборки используете, IDE и т. д.
Компиляция исходного кода Java
Вы можете скомпилировать исходный код Java непосредственно из вашей IDE(если вы используете IDE). Или вы можете использовать компилятор, который поставляется вместе с Java SDK. Чтобы выполнить компиляцию java кода из командной строки, сделайте следующее:
Каталог myfirstapp – это пакет в корневом каталоге исходного кода src. Если у вас есть несколько пакетов в корневом каталоге, вам придется запускать компилятор несколько раз. Java IDE обрабатывает это автоматически. Так же как и инструменты для сборки, такие как Ant, Maven или Gradle.
Выполнение скомпилированного кода
Когда вы запустите класс, ваша командная строка будет выглядеть примерно так(включая вывод из приложения):
Обратите внимание, что в первой команде не должно быть разрыва строки. Я добавил это только для того, чтобы было легче читать.
Создание, компиляция и выполнения Java программ
Перед тем как программа может быть выполнена, её необходимо создать и скомпилировать. Если в вашей программе возникли ошибки компиляции, вам необходимо изменить программу, чтобы исправить их, а затем перекомпилировать её. Если в вашей программе возникли ошибки выполнения, или она не приводит к правильному результату, вам необходимо изменить программу, перекомпилировать её и запустить снова. Этот процесс и является созданием (разработкой) программы.
Для создания и редактирования исходного кода Java вы можете использовать любой текстовый редактор или IDE. Этот раздел демонстрирует, как создавать, компилировать и запускать программы Java из командной строки. В разделе «Компиляция и запуск Java программ в NetBeans» показано, как это делать в IDE на примере NetBeans.
Можно вообще обойтись без IDE, а писать исходный код в любом текстовом редакторе (например, в Notepad), а компилировать в командной строке.
Внимание: файл с исходным кодом должен иметь расширение .java и иметь в точности такое же имя, как и имя публичного (public) класса. Например, файл с исходным кодом:
должен называться Welcome.java, поскольку имя public класса – Welcome.
Компилятор Java преобразовывает файл с исходным кодом Java в файл с байткодом Java. Следующая команда компилирует Welcome.java:
Если нет синтаксических ошибок, компилятор генерирует файл байкода с расширением .class. Следовательно, приведённая выше команда генерирует файл с названием Welcome.class.
Чтобы иметь возможность компилировать и запускать программы, вы должны установить JDK. Как это сделать описано в инструкциях:
Язык Java – это высокоуровневый язык программирования, но байткод Java – это низкоуровневый язык. Байткод похож на машинные инструкции, но нейтрален к архитектуре (не зависит от архитектуры) и может запускаться на любой платформе, которая имеет виртуальную машину Java – Java Virtual Machine (JVM). В отличие от физической машины, виртуальная машина – это программа, которая интерпретирует байткод Java. Это одно из главных преимуществ Java: байткод Java может работать на различных аппаратных платформах и операционных системах. Исходный код Java компилируется в байткод Java, а байткод Java интерпретируется виртуальной машиной Java. Ваш код Java может использовать код библиотеки Java. JVM выполняет ваш код вместе с кодом из библиотеки.
Выполнить Java программу – это значит запустить байткод программы. Вы можете выполнить байткод на любой платформе с JVM, которая является интерпретатором. Она (виртуальная машина Java) переводит отдельные инструкции байткода в целевой машинный языковой код. Это делается последовательно – одна инструкция за раз, а не вся программ за один присест. Каждый шаг немедленно выполняется, сразу после перевода.
Следующая команда выполняет байткод для программы, которая приведена выше:
На скриншоте ниже показан процесс компиляции и запуска:
Внимание: не используйте расширение .class в команде, когда запускаете программу. Используйте ИмяКласса для запуска программы. Если вы в командной строке используете ИмяКласса.class, то система будет пытаться работать с файлом ИмяКласса.class.class.
Справка: когда выполняется Java программа, JVM начинает с загрузки байткода класса в память, используя программу под названием загрузчик классов (class loader). Если ваша программа использует другие классы, загрузчик классов динамически подгружает их перед тем, как они понадобятся. После загрузки класса, JVM использует программу под названием контролёр байткода (bytecode verifier) для проверки правильности байткода и проверки, что байткод не нарушает ограничений безопасности Java. Java обеспечивает строгую защиту, чтобы убедиться, что файлы классов Java не подделаны и не вредят вашему компьютеру.
Педагогическое примечание: ваш инструктор может требовать от вас использовать пакеты для организации программ. Например, все программы из этой части можно поместить в пакет chapter2. Подробности о пакетах и пространствах имён будут рассмотрены далее. Также посмотрите раздел «Почему NetBeans всегда использует package».
Типичные ошибки компиляции и запуска Java программ
Команда javac не найдена
Если при запуске javac, т.е. при попытке компиляции Java программы вы получаете ошибку:
Это означает, что JDK не установлен. Либо установлен, но не настроены переменные окружения. Способы исправления очевидны:
Если JDK установлен, то можно обойтись без добавления переменной окружения. Для этого используйте абсолютный путь до исполнимого файла javac:
Ошибка Class names are only accepted if annotation processing is explicitly requested
Если попытаться скомпилировать программу следующим образом:
то возникнет ошибка:
Причина ошибки в том – что вы забыли указать расширение файла .java.
Ошибка записи (error while writing)
Компиляция заканчивается ошибкой:
Ошибка «class is public, should be declared in a file named»
который заканчивается примерной такой ошибкой
означает, что вы неправильно назвали класс в исходном коде программы. Имя класса должно совпадать с именем файла. В данном случае файл называется Welcome.java, а класс внутри программы назван Welcomee
Error: Could not find or load main class
Если попытаться запустить программу следующим образом:
то возникнет ошибка
Причина её в том, что не нужно было добавлять к названию файла расширение .class. Виртуальная машина автоматически добавляет расширение и в приведённом примере она ищет файл Welcome.class.class
Ошибка Error: Could not find or load main class при запуске Java программы по абсолютному пути
Эта ошибка возможно при запуске Java программы по абсолютному пути:
Ошибка возникает как в Windows, так и в Linux:
Если в терминале вы находитесь в той же директории, что и файл, который вы запускаете, то не нужно указывать абсолютный путь. Например, нужно запускать так:
Если же вы находитесь в другой директории, то нужно использовать опцию -cp, после которой указать путь до каталога, где размещена запускаемая программа. А далее указать запускаемый файл без расширения .class:
Как видно из скриншота, командная строка находится в папке C:\WINDOWS\system32. Файл, который нам нужно запустить, находится в папке C:\ (корень диска). Мы указываем после ключа -cp папку C:\, а затем пишем имя файла программы без расширения – Welcome.
Аналогично нужно поступать в Linux. Пример команды:
Ошибка Main method not found in class
Если при запуске вы столкнулись с ошибкой:
Это означает, что вы не указали метод main, либо написали слово неправильно (например, Main вместо main).
Особенности компиляции и запуска Java программ в Windows
Команда «javac» не является внутренней или внешней командой, исполняемой программой или пакетным файлом
Эта ошибка рассмотрена чуть выше. Для установки и настройки переменных окружения в Windows обратитесь к инструкции «Установка Java (JDK) в Windows».
Проблема с кодировкой в Java программах в командной строке Windows
Если вы написали программу, которая выводит кириллицу в консоль:
А в качестве результата получили крякозяблы:
Значит кодировка, в которой выводит строки ваша программа, отличается от кодировки командной строки Windows.
Имеется несколько способов исправить эту проблему. Кстати, если для запуска консольных программ Java вы используете NetBeans, то он выводит строки в правильной кодировке. В Linux эта проблема также отсутствует. Если вам нужно поменять кодировку на время, то вы можете выполнить следующие команды:
Для того, чтобы смена кодировки командной строки Windows не сбрасывалась после закрытия и открытия командной строки, можно внести изменения в реестр Windows. Для этого нажмите Win+x, выберите «Выполнить», в открывшееся окно введите regedit. В открывшейся программе (редактор реестра Windows) перейдите к [HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\Autorun] и измените (или добавьте) значение на @chcp 65001>nul
Инструменты для запуска и разработки Java приложений, компиляция, выполнение на JVM
Ни для кого не секрет, что на данный момент Java — один из самых популярных языков программирования в мире. Дата официального выпуска Java — 23 мая 1995 года.
Эта статья посвящена основам основ: в ней изложены базовые особенности языка, которые придутся кстати начинающим “джавистам”, а опытные Java-разработчики смогут освежить свои знания.
* Статья подготовлена на основе доклада Евгения Фраймана — Java разработчика компании IntexSoft.
В статье присутствуют ссылки на внешние материалы.
1. JDK, JRE, JVM
Java Development Kit — комплект разработчика приложений на языке Java. Он включает в себя Java Development Tools и среду выполнения Java — JRE (Java Runtime Environment).
Java development tools включают в себя около 40 различных тулов: javac (компилятор), java (лаунчер для приложений), javap (java class file disassembler), jdb (java debugger) и др.
Среда выполнения JRE — это пакет всего необходимого для запуска скомпилированной Java-программы. Включает в себя виртуальную машину JVM и библиотеку классов Java — Java Class Library.
JVM — это программа, предназначенная для выполнения байт-кода. Первое преимущество JVM — это принцип “Write once, run anywhere”. Он означает, что приложение, написанное на Java, будет работать одинаково на всех платформах. Это является большим преимуществом JVM и самой Java.
До появления Java, многие компьютерные программы были написаны под определенные компьютерные системы, а предпочтение отдавалось ручному управлению памятью, как более эффективному и предсказуемому. Со второй половины 1990-х годов, после появления Java, автоматическое управление памятью стало общей практикой.
Существует множество реализаций JVM, как коммерческих, так и с открытым кодом. Одна из целей создания новых JVM — увеличение производительности для конкретной платформы. Каждая JVM пишется под платформу отдельно, при этом есть возможность написать ее так, чтобы она работала быстрее на конкретной платформе. Самая распространённая реализация JVM — это JVM Hotspot от OpenJDK. Также есть реализации IBM J9, Excelsior JET.
2. Выполнение кода на JVM
Согласно спецификации Java SE, для того, чтобы получить код, работающий в JVM, необходимо выполнить 3 этапа:
3. Загрузчики классов и их иерархия
Вернемся к загрузчикам классов — это специальные классы, которые являются частью JVM. Они загружают классы в память и делают их доступными для выполнения. Загрузчики работают со всеми классами: и с нашими, и с теми, которые непосредственно нужны для Java.
Представьте ситуацию: мы написали свое приложение, и помимо стандартных классов там есть наши классы, и их очень много. Как с этим будет работать JVM? В Java реализована отложенная загрузка классов, иными словами lazy loading. Это значит, что загрузка классов не будет выполняться до тех пор, пока в приложении не встретится обращение к классу.
Иерархия загрузчиков классов
Первый загрузчик классов — это Bootstrap classloader. Он написан на C++. Это базовый загрузчик, который загружает все системные классы из архива rt.jar. При этом, есть небольшое отличие между загрузкой классов из rt.jar и наших классов: когда JVM загружает классы из rt.jar, она не выполняет все этапы проверки, которые выполняются при загрузке любого другого класс-файла т.к. JVM изначально известно, что все эти классы уже проверены. Поэтому, включать в этот архив какие-либо свои файлы не стоит.
Следующий загрузчик — это Extension classloader. Он загружает классы расширений из папки jre/lib/ext. Допустим, вы хотите, чтобы какой-то класс загружался каждый раз при старте Java машины. Для этого вы можете скопировать исходный файл класса в эту папку, и он будет автоматически загружаться.
Еще один загрузчик — System classloader. Он загружает классы из classpath’а, который мы указали при запуске приложения.
Процесс загрузки классов происходит по иерархии:
4. Структура Сlass-файлов и процесс загрузки
Перейдем непосредственно к структуре Class-файлов.
Все числа, строки, указатели на классы, поля и методы хранятся в Сonstant pool — области памяти Meta space. Описание класса хранится там же и содержит имя, модификаторы, супер-класс, супер-интерфейсы, поля, методы и атрибуты. Атрибуты, в свою очередь, могут содержать любую дополнительную информацию.
Таким образом, при загрузке классов:
5. Исполнение байт-кода на JVM
В первую очередь, для исполнения байт-кода, JVM может его интерпретировать. Интерпретация — довольно медленный процесс. В процессе интерпретации, интерпретатор “бежит” построчно по класс-файлу и переводит его в команды, которые понятны JVM.
Также JVM может его транслировать, т.е. скомпилировать в машинный код, который будет исполняться непосредственно на CPU.
Команды, которые исполняются часто, не будут интерпретироваться, а сразу будут транслироваться.
6. Компиляция
Компилятор — это программа, которая преобразует исходные части программ, написанные на языке программирования высокого уровня, в программу на машинном языке, “понятную” компьютеру.
Компиляторы делятся на:
Также компиляторы могут классифицироваться по моменту компиляции:
7. Организация памяти в Java
Стек — это область памяти в Java, которая работает по схеме LIFO — “Last in — Fisrt Out” или “Последним вошел, первым вышел”.
Он нужен для того, чтобы хранить методы. Переменные в стеке существуют до тех пор, пока выполняется метод в котором они были созданы.
Когда вызывается любой метод в Java, создается фрейм или область памяти в стеке, и метод кладется на его вершину. Когда метод завершает выполнение, он удаляется из памяти, тем самым освобождая память для следующих методов. Если память стека будет заполнена, Java бросит исключение java.lang.StackOverFlowError. К примеру, это может произойти, если у нас будет рекурсивная функция, которая будет вызывать сама себя и памяти в стеке не будет хватать.
Ключевые особенности стека:
Куча разбита на несколько более мелких частей, называемых поколениями:
Почему отказались от Permanent generation? В первую очередь, это из-за ошибки, которая была связана с переполнением области: так как Perm имел константный размер и не мог расширяться динамически, рано или поздно память заканчивалась, кидалась ошибка, и приложение падало.
Meta space же имеет динамический размер, и во время исполнения он может расширяться до размеров памяти JVM.
Ключевые особенности кучи:
Основываясь на информации выше, рассмотрим, как происходит управление памятью на простом примере:
У нас есть класс App, в котором единственный метод main состоит из:
— примитивной переменой id типа int со значением 23
— ссылочной переменной pName типа String со значением Jon
— ссылочной переменной p типа person
Как уже упоминалось, при вызове метода на вершине стека создаётся область памяти, в которой хранятся данные, необходимые этому методу для выполнения.
В нашем случае, это ссылка на класс person: сам объект хранится в куче, а в стеке хранится ссылка. Также в стек кладется ссылка на строку, а сама строка хранится в куче в String pool. Примитив хранится непосредственно в стеке.
Для вызова конструктора с параметрами Person (String) из метода main() в стеке, поверх предыдущего вызова main() создается в стеке отдельный фрейм, который хранит:
— this — ссылка на текущий объект
— примитивное значение id
— ссылочную переменную personName, которая указывает на строку в String Pool.
После того, как мы вызвали конструктор, вызывается setPersonName(), после чего снова создается новый фрейм в стеке, где хранятся те же данные: ссылка на объект, ссылка на строку, значение переменной.
Таким образом, когда выполнится метод setter, фрейм пропадет, стек очистится. Далее выполняется конструктор, очищается фрейм, который был создан под конструктор, после чего метод main() завершает свою работу и тоже удаляется из стека.
Если будут вызваны другие методы, для них будут также созданы новые фреймы с контекстом этих конкретных методов.
8. Garbage collector
В куче работает Garbage collector — программа, работающая на виртуальной машине Java, которая избавляется от объектов, к которым невозможно получить доступ.
Разные JVM могут иметь различные алгоритмы сборки мусора, также существуют разные сборщики мусора.
Мы поговорим о самом простом сборщике Serial GC. Сборку мусора мы запрашиваем при помощи System.gc().
Как уже было упомянуто выше, куча разбита на 2 области: New generation и Old generation.
New generation (младшее поколение) включает в себя 3 региона: Eden, Survivor 0 и Survivor 1.
Old generation включает в себя регион Tenured.
Что происходит, когда мы создаем в Java объект?
В первую очередь объект попадает в Eden. Если мы создали уже много объектов и в Eden уже нет места, срабатывает сборщик мусора и освобождает память. Это, так называемая, малая сборка мусора — на первом проходе он очищает область Eden и кладёт “выжившие” объекты в регион Survivor 0. Таким образом регион Eden полностью высвобождается.
Если произошло так, что область Eden снова была заполнена, garbage collector начинает работу с областью Eden и областью Survivor 0, которая занята на данный момент. После очищения выжившие объекты попадут в другой регион — Survivor 1, а два остальных останутся чистыми. При последующей сборке мусора в качестве региона назначения опять будет выбран Survivor 0. Именно поэтому важно, чтобы один из регионов Survivor всегда был пустым.
JVM следит за объектами, которые постоянно копируются и перемещаются из одного региона в другой. И для того, чтобы оптимизировать данный механизм, после определённого порога сборщик мусора перемещает такие объекты в регион Tenured.
Когда в Tenured места для новых объектов не хватает, происходит полная сборка мусора — Mark-Sweep-Compact.
Во время этого механизма определяется, какие объекты больше не используются, регион очищается от этих объектов, и область памяти Tenured дефрагментируется, т.е. последовательно заполняется нужными объектами.