Как написать программу на java
В этой статье речь идет об организации простейшего приложения на Java для начинающих разработчиков, которые уже изучили концепции объектного подхода. Но для опытных возможно тоже будет интересно.
Зачастую начинающие разработчики задают вопроc: «С чего начать создание приложения», какие классы использовать и прочее.
Не стоит воспринимать статью как пример «Hello World» для начинающих изучать язык Java и объектно-ориентированный подход. Предполагается, что читатель уже знаком с языком Java, однако у него возникают вопросы указанные выше.
В этой статье мы даем ответ на эти вопросы.
Для того, чтобы строить приложение постепенно, используя концепции объектно-ориентированного подхода мы будем представлять все элементы нашего приложения в виде объектов соответствующих классов. Поэтому приложение тоже будет отдельным классом. Для запуска приложения будем создавать его экземпляр.
Теперь более подробно…
Сначала создается класс Application — он будет моделью всего приложения.
Далее создаем точку входа в приложение — метод main:
Этот метод выполняется при запуске Java с указанием основого класса (Application). В нем мы создаем экземпляр приложения и инициализируем его, а далее запускаем. Для этого будем использовать методы init и run:
В методе init мы делаем необходимую инициализацию приложения. В методе run же распологается основной код хода приложения.
Метод init можно не использовать, однако мы исходим из того, что наше приложение проходит две стадии — инициализация и запуск.
Остальные элементы нашего приложения можно разбить на модельные классы и виды (окна, панели). Например, представим, что мы создаем простейший кредитный калькулятор. Тогда класс CreditCalculator — будет моделью калькулятора. В методе init будем инициализировать калькулятор, а в run вычислять:
Таким образом, создание приложения можно начать с создания класса Application и далее добавлять необходимые модельные классы с которыми требуется работать.
Теперь о том, как запустить приложение
Мы будем исходить из того, что вы используете среду разработки Eclipse, Intellij IDEA или NetBeans. И класс Application создали именно в ней. В этих же средах для запуска нужно вызвать контекстное меню и нажать Run… или Run As Application в редакторе класса Application.
Но все же — запуск приложения из среды не был нашей целью, а целью было понять с каких классов можно начать создание приложения.
Крутых девелоперов просьба не ругать — вы и так все знаете! А лучше поругайте — тогда будет понятно что неправильно.
wikiHow работает по принципу вики, а это значит, что многие наши статьи написаны несколькими авторами. При создании этой статьи над ее редактированием и улучшением работали, в том числе анонимно, 65 человек(а).
Java — это объектно-ориентированный язык программирования, созданный Джеймсом Гослингом в 1995 году, что означает выражение переменных как объектов с полями (которые являются атрибутами, описывающими объект) и методов (действия, которые объект может совершать). Java — это язык, позволяющий писать программы, которые могут быть запущены под любой виртуальной машиной Java. Поскольку это достаточно объемный по количеству слов язык программирования, его достаточно просто понять и изучить даже новичкам. В этом руководстве изложено введение к программированию на Java.
Для того чтобы начать писать программы на Java, в первую очередь установите среду разработчика. Многие программисты используют интегрированную среду разработки (англ. Integrated development environment — IDE), такую как Eclipse или Netbeans, но можно создать программу и без нее.
Любой программы по типу Блокнота будет достаточно для Java-программирования. Некоторые программисты предпочитают использовать текстовые редакторы на основе vim и emacs. Также существует достаточно хороший текстовый редактор, который можно установить как на ОС Windows так и Linux (Mac, Ubuntu и так далее) — Sublime Text. Его мы и будем использовать в данном обзоре.
- Если ваш компьютер работает под управлением операционной системы Windows и среда переменных работает некорректно, она может выдавать ошибку javac . Прочтите статью об установке комплекта разработчика приложений, чтобы получить более детальную информацию об установке для исключения этой ошибки.
Для начала мы создадим программу, которая будет выдавать надпись Hello World. Создайте новый файл в текстовом редакторе и сохраните его как "HelloWorld.java". "HelloWorld" — это имя класса, которое должно совпадать с названием файла, это важно.
Задайте класс и основной метод. Основной метод public static void main(String[] args) будет применяться при каждом запуске программы и будет устанавливаться в каждой последующей программе Java.
- Рассмотрим компоненты этой строки кода:
- System обращается к системе с указанием выполнять определенные действия.
- Out сообщает системе, что мы собираемся ввести какие-то данные.
- Println строка ввода — сообщает системе о необходимости вывести значение на экран.
- Скобки вокруг ("Hello World") обозначают, что метод System.out.println () выбирает это значение в качестве параметра.
- В конце каждой строчки кода нужно ставить точку с запятой.
- Java чувствителен к регистру, поэтому писать значения метода, переменных, и имя класса необходимо с учетом него.
- Блоки кода, которые относятся к определенному методу, разделяются фигурными скобками.
Соедините все вместе. В конечном итоге ваша программа Hello World должна выглядеть следующим образом:
Сохраните файл и откройте командную строку или терминал, чтобы скомпилировать программу. Зайдите в папку, где вы сохранили файл HelloWorld.java и введите в Javac (оптимизирующий компилятор языка java) HelloWorld.java. Таким образом, вы дадите знать компилятору, что хотите преобразовать файл. Если в процессе будут всплывать ошибки, компилятор уведомит вас о том, что вы сделали не так. В идеале у вас вообще не должно быть никаких уведомлений от компилятора в процессе преобразования файла. По окончании компиляции заглянете в папку, где был сохранен файл HelloWorld.java, — там должен появиться файл HelloWorld.class. Его и будет использовать для запуска виртуальная машина Java.
Запустите программу. Наконец-то мы добрались до этого момента! В командной строке или терминале введите in java HelloWorld. Виртуальная машина поймет таким образом, что вы хотите запустить класс HelloWorld. В консоли должна появиться надпись HelloWorld.
Java – один из самых востребованных языков программирования в мире и один из двух официальных языков программирования, используемых в разработке Android (другой – Kotlin). Разработчики, знакомые с Java, весьма востребованы и способны создавать широкий спектр различных приложений, игр и инструментов. С помощью этой краткой статьи по Java для начинающих вы сможете сделать свои первые шаги к тому, чтобы стать одним из таких разработчиков. Мы рассмотрим все, что вам нужно знать, чтобы начать работу, и поможем вам создать свое первое простое приложение.
Что такое Java?
Java-это объектно-ориентированный язык программирования, разработанный компанией Sun Microsystems в 1990-х годах (позже купленной Oracle).
Понятие «объектно-ориентированный» относится к способу написания структурного кода Java, а именно: разделение кода на так называемые «классы», которые запускаются вместе, чтобы обеспечить согласованное порождение объектов. Мы обсудим это позже, но достаточно сказать, что это приводит к универсальному и организованному коду, который легко редактировать и перепрофилировать.
Чтобы запустить и использовать Java, вам нужно три вещи:
- JDK – Java Development Kit
- JRE – Java Runtime Environment
- JVM – Java Virtual Machine
Виртуальная машина Java (JVM) гарантирует, что у ваших приложений Java есть доступ к минимальным ресурсам, необходимым для их запуска. Именно благодаря JVM программы Java так легко запускаются на разных платформах.
Среда исполнения Java (JRE) предоставляет собой «контейнер» для всех этих элементов и кода для запуска приложения. JDK – это «компилятор», который интерпретирует сам код и выполняет его. В JDK также есть инструменты разработчика, необходимые для написания кода Java (как и следует из названия).
Хорошая новость заключается в том, что разработчикам нужно только позаботиться о загрузке JDK, поскольку он поставляется вместе с двумя другими компонентами.
Как начать писать на Java
Если вы планируете разрабатывать приложения на Java на своем настольном компьютере, то вам нужно будет загрузить и установить JDK.
Вы можете получить последнюю версию JDK непосредственно с сайта Oracle. Как только вы установите его, ваш компьютер будет иметь возможность понимать и запускать код на Java. Тем не менее, вам все равно понадобится некоторое вспомогательное ПО, чтобы было действительно удобно писать код. Это так называемая «интегрированная среда разработки» или IDE: интерфейс, используемый разработчиками для ввода текста кода и вызова JDK.
При разработке для Android вы будете использовать IDE Android Studio. Она не только послужит интерфейсом для кода на Java (или Kotlin), но и станет мостом для доступа к специфичным для Android вызовам из SDK.
Насколько легко научиться программированию на Java?
Если вы новичок в разработке на Java, то ваши опасения вполне понятны. Так насколько же легко изучить Java?
Этот вопрос имеет несколько субъективную природу, но лично я бы отнес Java к языкам, не самым простым для изучения. Хотя он проще, чем C++, и часто описывается как более удобный для пользователя, но он, безусловно, не столь прост, как такие его конкуренты, как Python или BASIC, которые больше подходят для изучения начинающим программистам.
Конечно, задавшись конкретной целью – стать разработчиком приложений для Android, – проще всего сразу начать с языка, который уже поддерживается этой платформой.
Каков синтаксис Java?
Прежде чем мы погрузимся в самую суть этого руководства по Java для начинающих, стоит уделить некоторое время изучению синтаксиса Java.
Синтаксис Java относится к способу написания конкретных алгоритмов. Java очень принципиален в этом вопросе, и, если вы не пишете код определенным образом, то ваша программа не будет работать!
На самом деле я написал целую статью о синтаксисе Java для разработки Android, кратко перечислю особенности синтаксиса:
- Большинство строк должно заканчиваться точкой с запятой «;».
- Исключение составляет строка, открывающая новый блок кода. Она должна начинаться открытой фигурной скобкой «
- Код внутри блока кода должен иметь отступ, чтобы отделить его от остальных.
- Открытые блоки кода должны быть закрыты закрывающей фигурной скобкой «>».
- Комментарии – это строки, которым предшествуют символы «//».
Если вы нажимаете кнопку «запустить» или «скомпилировать» и получаете ошибку, то есть большая вероятность, что вы где-то пропустили точку с запятой!
Вы никогда не перестанете делать это, и это никогда не перестанет вас раздражать. Расслабьтесь!
С этими знаниями мы сможем глубже погрузиться в руководство по Java!
Основы Java: ваша первая программа
(Если же вы предпочитаете использовать другую IDE или стороннее приложение, это тоже прекрасно! Скорее всего, ваш новый проект будет состоять из аналогичного кода).
Удалите все, кроме следующего:
Это то, что мы, программисты, мы называем «шаблоном» (этот код скопирован из учебника Java от Фила Данфи). Шаблонный код – так можно назвать любой код, который встречается внутри практически любой программы.
Первая строка здесь определяет «класс», который по сути является модулем кода. Затем нам нужен метод внутри этого класса, который представляет собой небольшой блок кода, выполняющий задачу. В каждой программе Java должен быть метод main, так как он сообщает Java, где начинается программа.
Об остальном поговорим чуть ниже, не беспокойтесь. Все, что нам нужно знать для этого урока Java прямо сейчас, – это то, что код, который мы действительно хотим запустить, должен быть помещен в фигурные скобки под словом «main».
Поместите сюда следующий оператор:
Этот оператор напишет слова: «Hello world!» на вашем экране. Нажмите «Compile & Execute» и вы увидите его в действии.
Поздравляю! Вы только что написали свое первое Java-приложение!
Переменные в Java
Теперь пришло время рассказать о некоторых более важных вещах, лежащих в основе Java. Мало что может быть более фундаментальным в программировании, чем обучение использованию переменных!
Переменная по сути является «контейнером» для некоторых данных. Это означает, что вы выберете слово, которое будет представлять какое-то значение. Нам также необходимо определить переменные, основанные на типе данных, на которые они будут ссылаться.
Вот три основных типа переменных, которые мы собираемся ввести в этом руководстве по Java:
- Целые числа (integers) – как целые числа.
- Плавающие точки (floats) – или «переменные с плавающей точкой». Они содержат все числа, в том числе те, которые представляют десятичные дроби. «Плавающая точка» относится к десятичному разряду.
- Строки (strings)– строки содержат буквенно-цифровые символы и символы. Обычно строка используется для хранения чьего-то имени или, возможно, предложения.
Как только мы определяем переменную, мы можем вставить ее в наш код, чтобы изменить выходные данные. Например:
В этом примере кода мы определили строковую переменную с именем name . Мы сделали это, используя тип данных String , за которым следует имя нашей переменной, а затем данные. Когда вы помещаете что-то в двойные кавычки, то Java интерпретирует это дословно как строку.
Теперь мы печатаем на экране, как и раньше, но на этот раз заменяем «Hello world!» на «Hello + имя». Этот код показывает строку «Hello», за которой следует любое значение, содержащееся в следующей строковой переменной!
Самое замечательное в использовании переменных заключается в том, что они позволяют нам манипулировать данными, чтобы наш код мог вести себя динамически. Изменяя значение name , вы можете изменить поведение программы, не изменяя никакого фактического кода!
Условные операторы в Java
Еще одна из самых важных основ Java – это работа с условными операторами.
Условные операторы используют блоки кода, которые выполняются только при определенных условиях. Например, мы можем захотеть предоставить специальные пользовательские права основному пользователю нашего приложения.
Посмотрите на следующий код:
Запустите этот код, и вы увидите, что специальные разрешения предоставлены. Но, если вы измените значение name на что-то другое, то код не будет работать.
В этом коде используется оператор if . Он проверяет, является ли утверждение, содержащееся в скобках, истинным. Если это так, то будет запущен следующий блок кода. Не забудьте сделать отступ в коде, а затем закрыть блок в конце! Если оператор в скобках имеет значение false, то код просто пропустит этот раздел и продолжит работу с закрытых скобок.
Обратите внимание, что при наложении условия на данные мы используем два знака «=». Вы же используете только один, когда присваиваете какие-то данные переменным.
Методы на Java
Еще одна простая концепция, которую мы можем ввести в этом руководстве Java – это использование методов. Это даст вам немного больше понимания того, как структурирован Java-код и что с ним можно сделать.
Все, что мы собираемся сделать, – это взять часть кода, который мы уже написали, а затем поместить его в другой метод вне метода main :
Мы создали новый метод в строке, которая начинается со static void . Это означает, что метод определяет функцию, а не свойство объекта, и что он не возвращает никаких данных.
Но все, что мы вставляем в следующий блок кода, теперь будет выполняться каждый раз, когда мы «вызываем» метод, записывая его имя в нашем коде: grantPermission() . Затем программа выполнит этот блок кода и вернется к точке, из которой она вышла.
Передача аргументов в Java
Но самое замечательное в методах то, что они могут принимать переменные и манипулировать ими. Мы сделаем это, передав переменные в наши методы как «строки». Вот для чего и нужны скобки, следующие за названием метода.
В следующем примере я создал метод, который получает строковую переменную, названную nameCheck . Затем я могу обратиться к nameCheck из этого блока кода, и ее значение будет равно тому, что я поместил в фигурные скобки, когда вызвал метод.
Для этого руководства по Java я передал значение name методу и поместил туда оператор if . Таким образом, мы можем проверять несколько имен подряд, не набирая один и тот же код снова и снова.
Надеюсь, это даст вам представление о том, насколько мощными могут быть методы!
В завершение
Надеюсь, теперь у вас есть хорошее представление о том, как изучать Java. Вы даже можете сами написать какой-нибудь простой код: используя переменные и условные операторы, вы действительно можете заставить Java делать некоторые интересные вещи уже сейчас.
Следующий этап состоит в понимании объектно-ориентированного программирования и классов. Это понимание есть то, что действительно дает Java и подобным языкам их силу, но поначалу может быть немного сложным для осмысления.
Как вы знаете, Java — один из самых популярных языков программирования в мире и его знание существенно увеличит вашу значимость как программиста. Итак, вы решили начать писать на этом языке. Вам понадобится поставить JDK для того, чтобы писать и запускать программы на Java. JDK — набор софта, разработанного Oracle, содержащий в себе компилятор (javac), среду выполнения (Java Runtime Environment), стандартную библиотеку языка, примеры и документацию. Прочитав эту статью, вы узнаете, как установить и настроить JDK на своей системе, что такое среда разработки и какие варианты IDE существуют для Java. Также вы напишете свою первую программу на Java.
Установка Java Development Kit
- Перейдите на сайт Oracle и загрузите JDK для вашей платформы.
- После загрузки извлеките полученный архив и запустите извлеченное приложение.
- В процессе установке выберите вариант «Development Tool» и нажмите «Next».
- Спустя некоторое время установка завершится.
Итак, вы установили Java Development Kit, но это еще не всё. Необходимо настроить его для вашей системы.
Настройка JDK на примере Windows
- Перейдите в папку %ProgramFiles%\Java\%версия установленного вами jdk%\bin , нажмите на свойства любого файла в этой папке и скопируйте путь к нему.
- Перейдите в свойства вашего компьютера, откройте вкладку «Дополнительно», нажмите «Переменные среды…». В открывшемся окне создайте новую переменную, назовите её Path , в её значение вставьте скопированный ранее путь.
- Теперь самое важное. Откройте командную строку и наберите javac , чтобы убедиться, что JRE установлен и настроен. Если выдаётся список аргументов к команде javac , то поздравляю, вы успешно установили и настроили всё, что необходимо для использования Java!
После установки JDK и JRE не помешает установить на компьютер одну из IDE.
Установка IDE
Для начала разберёмся, что такое IDE.
IDE (Integrated Development Environment) — это комплекс программных средств, используемый программистами для разработки программного обеспечения. IDE позволяет с лёгкостью писать, запускать, отлаживать и тестировать код.
Для написания сложных программ целесообразно использовать IDE. Мы рассмотрим наиболее популярные.
Блокнот
Да, и в блокноте можно писать код! Для разработки вам потребуется всего лишь установить JDK и указать путь к ней. Пишете код в блокноте, компилируете с помощью командной строки. Тем не менее, для разработки сложных программ это не самый лучший вариант из-за отсутствия каких-либо дополнительных возможностей, присутствующих в продвинутых IDE.
NetBeans
NetBeans — выбор профессиональных Java-разработчиков. В ней есть уникальные возможности и инструменты, которые позволят вам сделать вашу программу кроссплатформенной, а код удобочитаемым. NetBeans поддерживает не только Java, но и другие языки программирования для десктоп- и веб-разработки. Она полностью бесплатна, скачать её можно с официального сайта. Вот лишь некоторые её возможности:
- форматирование кода;
- установка сторонних библиотек;
- простой графический интерфейс;
- и многое, многое другое…
Eclipse
- возможность форматировать код так, как вам удобно;
- поддержка разбиения кода на модули;
- лёгкость использования одного и того же кода в разных проектах;
- перетаскивание (drag-and-drop);
- просмотр содержимого библиотек;
- удобный интерфейс.
IntelliJ IDEA
IntelliJ IDEA — известная IDE для Java, написанная, как ни странно, на Java. Укомплектована уникальными инструментами и позволяет без проблем ориентироваться в программе. Нахождение ошибок и отладка кода никогда не были такими легкими, как с IntelliJ IDEA.
JCreator
JCreator — продвинутая и самая быстрая IDE для Java, написанная на C++.
Пишем свою первую программу
Итак, вы установили и настроили JDK, JRE и IDE для Java. Каков следующий шаг? Конечно же, написать программу, чтобы окончательно убедиться, что всё работает и вы готовы к изучению языка. Вы познакомитесь с базовой структурой кода на Java и создадите свою первую программу! Стоит отметить, что перед изучением Java следует ознакомиться хотя бы с самыми простыми принципами объектно-ориентированного программирования.
Структуру программы на Java можно представить так:
Структура программы на Java
В файле с исходным кодом содержится несколько классов — это части программы, имеющие определённые функции. Хорошей практикой считается разбиение программы на несколько файлов с исходным кодом, каждый со своим назначением. В классах содержатся методы — действия, которые могут выполнять объекты данного класса. В методе содержатся команды, с помощью которых вы можете получить желаемый результат.
Перед тем, как приступить к созданию программы, необходимо создать проект, а в нём и файл, в котором будет содержаться ваш код. Рассмотрим создание проекта на IDE Eclipse, но в остальных IDE процесс отличается не сильно. Cверху выберите «File», затем наведите курсор на «New», в открывшемся меню выберите «Java Project». В появившемся окне введите имя проекта и другие нужные вам настройки (если не уверены, что делать, то можно просто оставить все как есть) и нажмите «Next». Готово, вы создали проект! Осталось лишь создать в нём класс, в котором вы напишете свою первую программу. Щёлкните правой кнопкой мыши по вашему проекту (он должен появиться справа) и выберите «New» → «Class». Присвойте новому классу имя (в данном примере — это first ) и нажмите «Finish».
Приступим к написанию вашей первой программы. По традиции — это программа, выводящая на экран «Hello, world!».
Разберём по частям написанное нами:
Ни для кого не секрет, что на данный момент 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 этапа:
- Загрузка байт-кода и создание экземпляра класса Class
Грубо говоря, чтобы попасть на 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’а, который мы указали при запуске приложения.
Процесс загрузки классов происходит по иерархии:
- В первую очередь мы запрашиваем поиск в кэше System Class Loader (кэш системного загрузчика содержит классы, которые уже были им загружены);
- Если класс не был найден в кэше системного загрузчика, мы смотрим кэш Extension class loader;
- Если класс не найден в кэше загрузчика расширений, класс запрашивается у загрузчика Bootstrap.
4. Структура Сlass-файлов и процесс загрузки
Перейдем непосредственно к структуре Class-файлов.
Один класс, написанный на Java, компилируется в один файл с расширением .class. Если в нашем Java файле лежит несколько классов, один файл Java может быть скомпилирован в несколько файлов с расширением .class — файлов байт-кода данных классов.
Все числа, строки, указатели на классы, поля и методы хранятся в Сonstant pool — области памяти Meta space. Описание класса хранится там же и содержит имя, модификаторы, супер-класс, супер-интерфейсы, поля, методы и атрибуты. Атрибуты, в свою очередь, могут содержать любую дополнительную информацию.
Таким образом, при загрузке классов:
- происходит чтение класс-файла, т.е проверка корректности формата
- создается представление класса в Constant pool (Meta space)
- грузятся супер-классы и супер-интерфейсы; если они не будут загружены, то и сам класс не будет загружен
5. Исполнение байт-кода на JVM
В первую очередь, для исполнения байт-кода, JVM может его интерпретировать. Интерпретация — довольно медленный процесс. В процессе интерпретации, интерпретатор “бежит” построчно по класс-файлу и переводит его в команды, которые понятны JVM.
Также JVM может его транслировать, т.е. скомпилировать в машинный код, который будет исполняться непосредственно на CPU.
Команды, которые исполняются часто, не будут интерпретироваться, а сразу будут транслироваться.
6. Компиляция
Компилятор — это программа, которая преобразует исходные части программ, написанные на языке программирования высокого уровня, в программу на машинном языке, “понятную” компьютеру.
Компиляторы делятся на:
- Не оптимизирующие
- Простые оптимизирующие (Hotspot Client): работают быстро, но порождают неоптимальный код
- Сложные оптимизирующие (Hotspot Server): производят сложные оптимизирующие преобразования прежде чем сформировать байт-код
Также компиляторы могут классифицироваться по моменту компиляции:
- Динамические компиляторы
Работают одновременно с программой, что сказывается на производительности. Важно, чтобы эти компиляторы работали на коде, который часто исполняется. Во время исполнения программы JVM знает, какой код выполняется чаще всего, и, чтобы постоянно не интерпретировать его, виртуальная машина сразу переводит его в команды, которые уже будут исполняться непосредственно на процессорe. - Статические компиляторы
Дольше компилируют, но порождают оптимальный код для исполнения. Из плюсов: не требуют ресурсов во время исполнения программы, каждый метод компилируется с применением оптимизаций.
7. Организация памяти в Java
Стек — это область памяти в Java, которая работает по схеме LIFO — “Last in — Fisrt Out” или “Последним вошел, первым вышел”.
Он нужен для того, чтобы хранить методы. Переменные в стеке существуют до тех пор, пока выполняется метод в котором они были созданы.
Когда вызывается любой метод в Java, создается фрейм или область памяти в стеке, и метод кладется на его вершину. Когда метод завершает выполнение, он удаляется из памяти, тем самым освобождая память для следующих методов. Если память стека будет заполнена, Java бросит исключение java.lang.StackOverFlowError. К примеру, это может произойти, если у нас будет рекурсивная функция, которая будет вызывать сама себя и памяти в стеке не будет хватать.
Ключевые особенности стека:
- Стек заполняется и освобождается по мере вызова и завершения новых методов
- Доступ к этой области памяти осуществляется быстрее, чем к куче
- Размер стека определяется операционной системой
- Является потокобезопасным, поскольку для каждого потока создается свой отдельный стек
Куча разбита на несколько более мелких частей, называемых поколениями:
- Young generation — область, где размещаются недавно созданные объекты
- Old (tenured) generation — область, где хранятся “долгоживущие” объекты
- До Java 8 существовала ещё одна область — Permanent generation — которая содержит метаинформацию о классах, методах, статических переменных. После появления Java 8 было решено хранить эту информацию отдельно, вне кучи, а именно в Meta space
Почему отказались от Permanent generation? В первую очередь, это из-за ошибки, которая была связана с переполнением области: так как Perm имел константный размер и не мог расширяться динамически, рано или поздно память заканчивалась, кидалась ошибка, и приложение падало.
Meta space же имеет динамический размер, и во время исполнения он может расширяться до размеров памяти JVM.
Ключевые особенности кучи:
- Когда эта область памяти заполняется полностью, Java бросает java.lang.OutOfMemoryError
- Доступ к куче медленнее, чем к стеку
- Для сбора неиспользуемых объектов работает сборщик мусора
- Куча, в отличие от стека, не является потокобезопасной, так как любой поток может получить к ней доступ
Основываясь на информации выше, рассмотрим, как происходит управление памятью на простом примере:
У нас есть класс 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 дефрагментируется, т.е. последовательно заполняется нужными объектами.
Заключение
В данной статье мы разобрали базовые инструменты языка Java: JVM, JRE, JDK, принцип и этапы выполнения кода на JVM, компиляцию, организацию памяти, а также принцип работы сборщика мусора.Читайте также: