JVM – что это? Как устроена виртуальная машина Java
Виртуальная машина Java («Java Virtual Machine» — JVM) — это основная часть платформы Java Runtime Environment (JRE), которая интерпретирует байт-код Java для запуска программ.
Одним из наиболее значительных преимуществ использования является использование JVM для запуска программы Java в любой операционной среде. В её основе реализуется принцип WORA (Write once, run anywhere — «написал один раз, запускай везде»), который сильно упростил процессы разработки.
Как правило, считается, что JVM имеет двойное определение — техническое и неформальное.
Техническое: JVM — это спецификация программы, которая обеспечивает среду выполнения кода Java.
Неофициальное: JVM запускает приложения Java, c помощью настроенных параметров для управления всеми программными ресурсами.
Что делает виртуальная машина Java
JVM выполняет две основные функции:
- позволяет запускать Java-программы на любом устройстве или в любой операционной системе;
- даёт доступ к управлению памятью программ и её оптимизации.
Поскольку JVM — это хорошо известная среда выполнения со стандартизированной конфигурацией, мониторингом и управлением, она естественным образом подходит для контейнерной разработки с использованием таких технологий, как Docker.
Роль Java Virtual Machine
Теперь давайте более подробно рассмотрим место виртуальной машины Java в выполняемых процессах.
Если вы внимательно посмотрите на схему, добавленную выше, то будет несложно догадаться, что JVM образует слой между операционной системой и программами Java.
Это означает, что скомпилированная Java-программа будет связываться с Java Virtual Machine, а JVM будет общаться с операционной системой, являясь своего рода посредником между скомпилированными файлами классов и операционной системой.
Файл .class и байт-код
Когда дело доходит до выполнения программы, главное, что интересует виртуальную машину Java — это определённый формат файла – .class.
Файлы классов содержат наполовину скомпилированный код, называемый байт-кодом, который в свою очередь предоставляет JVM инструкции, таблицу символов и другую вспомогательную информацию.
Архитектура виртуальной машины Java
Понять, что такое виртуальная машина Java, будет немного проще, если познакомиться с её архитектурой и тем, как она работает. Поэтому важно рассмотреть строение JVM и особенности её частей.
Java Virtual Machine состоит из трёх отдельных компонентов:
- загрузчик классов;
- область памяти;
- исполнительный механизм.
(4).jpg)
Загрузчики классов отвечают за динамическую загрузку файлов .class в виртуальную машину Java и сохранения байт-кода в области метода JVM, о которой мы поговорим чуть позже.
Загрузчик классов Java бывает трёх типов:
- BootStrap ClassLoader (Загрузчик классов начальной загрузки) — это машинный код, который запускает операцию, когда её вызывает JVM. Его задача — загрузить классы из папки rt.jar.
- Extension ClassLoader (Загрузчик классов расширений) является дочерним элементом Bootstrap ClassLoader и загружает расширения основных классов Java из каталога jre/lib/ext или любого другого каталога, на который указывает java.ext.dirs.
- System ClassLoader (Системный загрузчик классов) загружает классы, найденные в переменной среды CLASSPATH, -classpath или параметре командной строки -cp.
- Область памяти
Область памяти или, как её ещё называют, область данных времени выполнения JVM состоит из 5 частей:
- Область метода предназначена для хранения данных файлов .class: например, метаданные, данные полей и методов, а также код метода. Область метода создаётся автоматически при запуске виртуальной машины, и для каждой ВМ существует только одна область метода.
- Область кучи. В куче хранятся все объекты и соответствующие им переменные экземпляра. Когда мы создаём новый экземпляр класса, он сразу же загружается в область кучи, которая остается единственной во время выполнения задачи.
- Область стека. В неё загружаются все локальные переменные, вызовы методов и частичные результаты.
- Регистры ПК. В регистре ПК хранится адреса виртуальных машин Java, выполняющих операцию в данный момент. В Java каждый поток получает свой собственный регистр ПК.
- Стеки нативных методов. Нативные методы — это методы, написанные на C или C++. Виртуальная машина JVM хранит стеки, которые поддерживают такие методы, с отдельным стеком собственных методов, выделенным для каждого потока.
- Исполнительный механизм
Этот тип программного обеспечения используется для тестирования оборудования и программного обеспечения. При этом он не сохраняет никакой информации о тестируемом продукте.
- интерпретатора;
- JIT-компилятора;
- сборщика мусора.
Перед выполнением программы интерпретатор и компилятор JIT («Just-in-time» — «точно в нужное время») преобразуют байт-код в машинные инструкции. Интерпретатор делает это построчно.
В тот момент, когда в сценарии обнаруживается повторяющийся код, к нему подключается JIT-компилятор для ускорения операции. Затем он компилирует байт-код и заменяет его собственным кодом. Такой процесс повышает производительность всей системы.
Но за что же в таком случае отвечает сборщик мусора? В некоторых других языках программирования (таких как C++) освобождение памяти от объектов без циклических ссылок зависит лишь от самого программиста. Однако в JVM этим занимается сборщик мусора, что оптимизирует использование памяти.
Важно отметить, что сборка мусора выполняется в JVM автоматически через определённые отрезки времени и не требует отдельного внимания специалистов. Конечно, этот процесс можно попробовать принудительно запустить, вызвав System.gc(), но нет никакой гарантии, что это сработает.
Заключение
Несмотря на то, что виртуальная машина Java изначально предназначалась только для запуска и выполнения программ Java, на сегодняшний день она способна поддерживать многие языки сценариев и программирования, что лишь укрепило популярность данной платформы.
В этой статье мы познакомились с виртуальной машиной Java, её архитектурой и основными компонентами, а также поговорили о месте JVM в запрашиваемых системой операциях.
Что такое JVM? Знакомство с виртуальной машиной Java

Java virtual machine (JVM) — это программа, которая разработана для выполнения и запуска других программ на основе Java. В основе JVM лежит простая и гениальная идея, которая всегда останется одним из величайших примеров программирования в стиле кунг-фу. JVM может также использоваться для выполнения программ, написанных на других языках программирования. Подробно рассказываем, как работает JVM, для чего используется эта технология и почему она является одним из главных компонентов в платформе Java. Материал основан на статье Java-разработчика Matthew Tyson «What is the JVM? Introducing the Java Virtual Machine».
- Для чего используется Java virtual machine
- Кто разрабатывает и обслуживает JVM?
- Сборка мусора
- Три главные части JVM
- Спецификация JVM
- Реализация JVM
- Экземпляр JVM
- Загрузчик классов в JVM
- Механизм выполнения в JVM
Для чего используется Java virtual machine
JVM имеет две основные функции:
- Позволяет запускать программы, написанные на Java, на любых устройствах или операционных системах. Так реализуется принцип Java — «Написал один раз, запускай везде».
- Управляет и оптимизирует память, которую используют программы.
Во время выхода первой версии Java в 1995 году все программы писались для конкретной операционной системы, а памятью управлял разработчик программного обеспечения. Поэтому появление JVM стало революцией на рынке.
Существует два основных определения JVM — техническое и повседневное:
- Техническое определение: JVM — это софт, который выполняет код и предоставляет среду для его выполнения.
- Повседневное определение: JVM — это способ запуска наших Java-приложений. Мы настраиваем параметры JVM, а потом полагаемся на ее автоматическое управление ресурсами во время выполнения.
Когда разработчики говорят о JVM, обычно имеется в виду процесс, который выполняется на нашем устройстве, особенно на сервере — он управляет и контролирует использование ресурсов Java-приложения.
Кто разрабатывает и обслуживает JVM?
На сегодняшний день JVM массово используется и развивается в разных проектах — как коммерческих, так и Open Sourse. Например, существует проект OpenJDK, который представляет собой полностью совместимый Java Development Kit, состоящий исключительно из свободного и открытого исходного кода. При этом, несмотря на открытость кода этого проекта, его разработкой практически полностью занимается корпорация Oracle.
Сборка мусора
В Java памятью управляет JVM с помощью процесса, который называется сборкой мусора — он непрерывно определяет и удаляет неиспользуемую память в Java-приложениях. Сборка мусора происходит внутри работающей JVM.
В начале существования Java подвергалась серьезной критике за то, что не была «Close to the metal» как C++, поэтому не была такой быстрой. Особенно спорным критики называли процесс сборки мусора. С тех пор были предложены и использованы различные алгоритмы и подходы, которые значительно улучшили и оптимизировали сборку мусора.
Три главные части JVM
JVM состоит из трех основных частей: спецификация, реализация и экземпляр. Рассмотрим каждую из них.
Спецификация JVM
Первая часть JVM — спецификация , которая до конца не определяет все детали реализации виртуальной машины. Это значит, что остается максимальная свобода творчества для разработчика, который работает с ней. Чтобы правильно реализовать виртуальную машину Java, вам нужно всего лишь уметь читать class-файлы и правильно выполнять указанные в них операции.
Итак, все, что должна делать JVM — правильно запускать Java-программы. Это может показаться достаточно простым процессом, однако это очень масштабная задача, учитывая мощность и гибкость языка Java.
Реализация JVM
Реализация спецификации JVM приводит к созданию реальной программы, которая и является реализацией JVM. По сути, существует огромное количество реализаций спецификации JVM — как коммерческих, так и с открытым кодом.
Экземпляр JVM
После того, как спецификация JVM реализована и выпущена в качестве самостоятельной программы, вы можете загрузить ее как приложение. Эта загруженная программа является экземпляром виртуальной машины.
Чаще всего, когда разработчики говорят о JVM, они имеют ввиду экземпляр JVM, который работает в среде разработки. Вы можете сказать: «Привет, сколько памяти использует JVM на этом сервере?» или «Я не могу поверить, что сделал зацикленный вызов, а переполнение стека сломало мою JVM. А ведь это просто ошибка новичка!»
Загрузка и выполнение class-файлов в JVM
Мы говорили о роли JVM в запуске Java-приложений, но как виртуальная машина выполняет свою функцию? Для запуска Java-приложений JVM зависит от загрузчика классов и механизма выполнения Java.
Загрузчик классов в JVM
Все в Java — классы, и все Java-приложения состоят из классов. Любое приложение может состоять из одного или многих тысяч классов. Чтобы запустить Java-приложение, JVM должна загрузить скомпилированные .class-файлы в контекст — например, в сервер, где они будут доступны. JVM зависит от своего загрузчика класса для корректного выполнения этой функции.
Загрузчик классов Java является частью JVM — он загружает классы в память и делает их доступными для выполнения. Загрузчик классов использует технику ленивой загрузки (lazy-loading) и кэширование, чтобы сделать загрузку классов максимально эффективной. При этом использование таких методов считается достаточно простым процессом.
Все виртуальные машины Java включают в себя загрузчики классов. Спецификация JVM описывает стандартные методы для запроса и управления загрузчиком во время работы, но за выполнение этих возможностей отвечает конкретная реализация JVM. С точки зрения разработчика, механизмы, лежащие в основе загрузчика классов, обычно представляют собой черный ящик.
Механизм выполнения в JVM
После того, как загрузчик классов завершил свою работу, JVM начинает выполнять код каждого класса. Механизм выполнения — компонент JVM, который обрабатывает функции, и он необходим для корректной работы любой виртуальной машины Java.
Выполнение кода включает управление доступом к системным ресурсам. Механизм выполнения JVM находится между работой программы, с ее запросами на файловые, сетевые ресурсы и ресурсы памяти, и операционной системой, которая предоставляет эти ресурсы.
Управление системными ресурсами
Системные ресурсы могут быть разделены на две больших категории: память и все остальное.
JVM отвечает за очистку неиспользуемой памяти, при этом сборщик мусора — это механизм, который и осуществляет этот процесс. JVM также отвечает за распределение и поддержание ссылочной структуры, которую любой разработчик принимает как само собой разумеющееся. Например, механизм выполнения JVM отвечает за то, что при использовании ключевого слова new происходит запрос к операционной системе на выделение памяти.
Помимо памяти, механизм выполнения управляет ресурсами файловой системы и сети. Поскольку JVM совместима с различными операционными системами, то эта задача считается достаточно сложной. Помимо потребностей каждого приложения в ресурсах, механизм выполнения должен корректно работать с каждой операционной системой.
Эволюция JVM: прошлое, настоящее, будущее
В 1995 году разработчики JVM представили две революционные концепции, которые с тех пор стали стандартом в разработке: «Написал один раз, запускай везде» и автоматическое управление памятью. В то время совместимость софта была смелой концепцией, но сейчас это стало нормой. Точно так же, как современное поколение живет с автоматической сборкой мусора.
Можно сказать, что если Джеймс Гослинг и Брендан Эйх изобрели современное программирование, то тысячи других разработчиков усовершенствовали и развили их идеи в последующие десятилетия. Изначально виртуальная машина Java предназначалась только для Java, но сегодня она эволюционировала до поддержки многих языков программирования, включая Scala, Groovy и Kotlin.
Изучайте Java на Хекслете Вступайте в профессию и изучайте один из самых востребованных в энтерпрайзе языков программирования.
Компиляция и исполнение Java приложений под капотом

Всем привет! Сегодня я хотел бы поделиться знаниями о том, что происходит под капотом JVM (Java Virtual Machine) после того, как мы запускаем написанное Java приложение. В наше время существуют моднейшие среды разработки, которые помогают не думать о внутреннем устройстве JVM, компиляции и выполнении Java-кода, из за чего новые разработчики могут упустить эти важные аспекты. В то же время, на собеседованиях часто задают вопросы касательно этой темы, из-за чего я и решил написать статью.
2. Компиляция в байт-код

Начнем с теории. Когда мы пишем какое-либо приложение, мы создаем файл с расширением .java и помещаем в него код на языке программирования Java. Такой файл, содержащий код, понятный человеку, называется файлом с исходным кодом. После того, как файл с исходным кодом готов, нужно его выполнить! Но на стадии в нем содержится информация, понятная только человеку. Java — мультиплатформенный язык программирования. Это значит, что программы, написанные на языке Java, можно выполнять на любой платформе, где установлена специальная исполняющая система Java. Такая система называется Java Virtual Machine (JVM). Для того, чтобы перевести программу из исходного кода в код, понятный JVM, нужно её скомпилировать. Код, понятный JVM называется байт-кодом и содержит набор инструкций, которые в дальнейшем будет исполнять виртуальная машина. Для компиляции исходного кода в байт-код существует компилятор javac , входящий в поставку JDK (Java Development Kit). На вход компилятор принимает файл с расширением .java , содежащий исходный код программы, а на выходе выдает файл с расширением .class , содержащий байт-код, необходимый для исполнения программы виртуальной машиной. После того, как программа была скомпилирована в байт-код, она может быть выполнена с помощью виртуальной машины.
3. Пример компиляции и выполнения программы
Предположим, что у нас есть простая программа, содержащаяся в файле Calculator.java , которая принимает 2 численных аргумента командной строки и печатает результат их сложения:
class Calculator < public static void main(String[] args)< int a = Integer.valueOf(args[0]); int b = Integer.valueOf(args[1]); System.out.println(a + b); >>Для того, чтобы скомпилировать эту программу в байт-код, воспользуемся компилятором javac в командной строке:
javac Calculator.javaПосле компиляции на выходе мы получаем файл с байт-кодом Calculator.class , который мы можем исполнить при помощи установленной на нашем компьютере java-машины командой java в командной строке:
java Calculator 1 2Заметим, что после названия файла были указаны 2 аргумента командной строки — числа 1 и 2. После выполнения программы, в командной строке выведется число 3. В примере выше у нас был простой класс, который живет сам по себе. Но что, если класс находится в каком либо пакете? Смоделируем такую ситуацию: создадим директории src/ru/javarush и поместим туда наш класс. Теперь он выглядит следующим образом (добавили имя пакета в начале файла):
package ru.javarush; class Calculator < public static void main(String[] args)< int a = Integer.valueOf(args[0]); int b = Integer.valueOf(args[1]); System.out.println(a + b); >>Скомпилируем такой класс следующей командой:
javac -d bin src/ru/javarush/Calculator.javaВ этом примере мы использовали дополнительную опцию компилятора -d bin , которая складывает скомпилированные файлы в директорию bin со структурой, аналогичной директории src , при этом директория bin должна быть создана заранее. Такой прием используется, чтобы не путать файлы с исходным кодом с файлами с байт-кодом. Перед запуском скомпилированной программы стоит пояснить понятие classpath . Classpath — это путь, относительно которого виртуальная машина будет искать пакеты и скомпилированные классы. Тоесть, таким образом мы говорим виртуальной машине какие директории в файловой системе являются корневыми для иерархии пакета Java. Classpath можно укзать при запуска программы с помощью флага -classpath . Запуск программы осуществляем с помощью команды:
java -classpath ./bin ru.javarush.Calculator 1 2В этом примере нам потребовалось указать полное имя класса, включая имя пакета, в котором он находится. Финальное дерево файлов выглядит следующим образом:
├── src │ └── ru │ └── javarush │ └── Calculator.java └── bin └── ru └── javarush └── Calculator.class4. Выполнение программы виртуальной машиной
Итак, мы запустили написанную программу. Но что же происходит в момент запуска скомпилированной программы виртуальной машиной? Для начала разберемся, что означают понятия компиляции и интерпретации кода. Компиляция — трансляция программы, составленной на исходном языке высокого уровня, в эквивалентную программу на низкоуровневом языке, близком машинному коду. Интерпретация — пооператорный (покомандный, построчный) анализ, обработка и тут же выполнение исходной программы или запроса (в отличие от компиляции, при которой программа транслируется без её выполнения). Язык Java обладает как компилятором ( javac ), так и интерпретатором, в роли которого выступает виртуальная машина, которая построчно преобразует байт-код в машинный код и тут же его исполняет. Таким образом, когда мы запускаем скомпилированную программу, виртуальная машина начинает её интерпретацию, то есть построчное преобразование байт-кода в машинный код, а так же его исполнение. К сожалению, чистая интерпретация байт-кода является довольно долгим процессом и делает язык java медленным в сравнении с его конкурентами. Дабы избежать этого, был введен механизм, позволяющий ускорить интерпретацию байт-кода виртуальной машиной. Этот механизм называется Just-in-time компиляцией (JITC).
5. Just-in-time (JIT) компиляция
Простыми словами, механизм Just-In-Time компиляции заключается в следующем: если в программе присутствуют части кода, которые выполняются много раз, то их можно скомпилировать один раз в машинный код, чтобы в будущем ускорить их выполнение. После компиляции такой части программы в машинный код, при каждом следующем вызове этой части программы виртуальная машина будет сразу выполнять скомпилированный машинный код, а не интерпретировать его, что естественно ускорит выполнение программы. Ускорение работы программы достигается за счет увеличения потребления памяти (где-то же нам нужно хранить скомпилированный машинный код!) и за счет увеличения временных затрат на компиляцию во время исполнения программы. JIT компиляция — довольно сложный механизм, поэтому пройдемся по верхам. Всего существует 4 уровня JIT компиляции байт-кода в машинный код. Чем выше уровень компиляции, тем он сложнее, но и одновременно выполнение такого участка будет быстрее, чем участка с меньшим уровнем. JIT — компилятор самостоятельно решает, какой уровень компиляции задать для каждого фрагмента программы на основе того, как часто выполняется этот фрагмент. Под капотом JVM использует 2 JIT-компилятора — C1 и C2. C1 компилятор так же называется клиентским компилятором и способен скомпилировать код только до 3-его уровня. За 4-ый, самый сложны и быстрый уровень компиляции отвечает компилятор C2.

Из вышесказанного можно сделать вывод о том, что для простых, клиентских приложений, выгоднее использовать компилятор C1, так как в этом случае нам важно как быстро стартует приложение. Серверные, долгоживущие приложения могут стартовать большее количество времени, однако в дальнейшем должны работать и выполнять свою функцию быстро — тут нам подойдет компилятор C2.
При запуске Java — программы на x32 версии JVM мы в ручную можем указать, какой режим мы хотим использовать, при помощи флагов -client и -server . При указании флага -client JVM не будет производить сложные оптимизации с байт-кодом, что ускорит время старта приложения и уменьшит количество потребляемой памяти. При указании флага -server приложение будет стартовать большее количество времени из-за сложных оптимизаций байт-кода и будет использовать больше памяти для хранения машинного кода, однако в дальнейшем работать такая программа будет быстрее. В x64 версии JVM флаг -client игнорируется и по умолчанию используется серверная конфигурация приложения.
6. Заключение
Компилятор javac преобразует исходный код программы в байт-код, который может быть выполнен на любой платформе, на которой установлена виртуальная машина Java;
После компиляции JVM интерпретирует получившийся байт-код;
Для ускорения работы Java-приложений, JVM использует механизм Just-In-Time компиляции, который преобразует наиболее часто выполняемые участки программы в машинный код и хранит их в памяти.
Как устроена Java Virtual Machine и её экосистема: подробный гайд
Иван Углянский рассказал, как устроена JVM, что с ней не так и зачем Python, Ruby и другие языки переезжают на виртуальную машину Java.


Иллюстрация: Mark Kingston / WikiMedia Commons / Colowgee для Skillbox Media

Антон Сёмин
Пишет об истории IT, разработке и советской кибернетике. Знает Python, JavaScript и немного C++, но предпочитает писать на русском.

об эксперте
JVM engineer. Работает в Excelsior@Huawei над виртуальными машинами Java, компиляторами и новыми языками программирования. Один из основателей и лидеров JUGNsk, член программного комитета SnowOne Conference.
ссылки
Я занимаюсь JVM более 10 лет. Начинал в новосибирской компании Excelsior, которая разрабатывала свою реализацию виртуальной машины Java — Excelsior JET. Потом мы вошли в состав Huawei, но команда осталась прежней.
Что такое JVM и как она спасла программистов от профессионального «подгорания»
До появления Java, примерно 25 лет назад, многие приложения писали на С или С++. У этих языков есть проблема: разработчику приходится думать, на какой операционке и архитектуре процессора будет работать его код. Например, если он пишет программу под Linux, то, скорее всего, она не запустится на Windows или MacOS. Поэтому код приходилось пичкать директивами условной компиляции или писать отдельную версию для каждой операционки.
Самую сильную боль вызывали приложения с GUI — код графических компонентов для разных операционок был совершенно разным. Причина в том, что C и C++ довольно близки к железу, а значит, сишник должен учитывать архитектуру процессора и тип операционной системы. Понятно, что никакой кроссплатформенностью здесь и не пахнет.
Ещё в 1960-е годы у инженеров появилась идея: писать программы не для конкретного железа, а для абстрактного «исполнителя». Программы на Java как раз пишутся для такого исполнителя — виртуальной машины, или Java Virtual Machine (JVM). Java-разработчик не задумывается, на какой платформе будет запускаться его код. В то же время виртуальная машина не знает, что исполняет инструкции на Java, ведь она принимает и исполняет байт-код.
В этом и было «уникальное торговое предложение» Java: разработчики писали программу под Windows, а она запускалась на macOS почти без изменений. Сейчас это звучит вполне естественно, а 25 лет назад казалось настоящим чудом.

Кроссплатформенность в Java обеспечивается явным разделением уровней языка и реализации.
Языковой уровень. Разработчики пишут код на языке Java, синтаксис и семантика которого описаны в Java Language Specification. После этого специальным инструментом, который называется javac, исходный код компилируется в байт-код Java. При этом происходит проверка синтаксиса, и в случае его нарушения разработчик получает сообщение об ошибке от javac.
Что здесь важно:
- На этом этапе нет ничего платформенно-специфичного, весь код на языке Java (как и байт-код Java) универсален.
- Байт-код Java — это язык, предназначенный не для людей, а для машин. Обычному разработчику его читать не нужно.
Уровень реализации. Полученный байт-код Java передаётся на вход виртуальной машины Java. И вот как именно она будет его исполнять, описано уже в другой спецификации — Java Virtual Machine Specification. Со всеми особенностями конкретной операционной системы или архитектуры процессора тоже разбирается JVM, без влияния на исходный код на языке Java. Таким образом, происходит перенос ответственности: разработчики на Java о таких неприятных вещах больше не думают, им достаточно просто взять правильную JVM (например, для Linux x64). А все OS/arch-специфические нюансы решают разработчики JVM.
Язык Java и сама JVM разрабатываются параллельно, при этом новые фичи языка зачастую требуют поддержки внутри JVM. С другой стороны, различные реализации JVM развиваются и сами по себе, например в них появляются новые, более эффективные алгоритмы сборки мусора или оптимизации кода.
У разделения языка и его реализации есть замечательное следствие: разработчику не обязательно ограничиваться языком Java, ведь виртуальная машина понятия не имеет, откуда взяли байт-код, который пришёл к ней на вход, был ли это изначально Java-код или что-то другое. То есть программу можно писать на любом языке, который транслируется в байт-код. И таких языков — целое семейство: Kotlin, Clojure, Groovy и так далее. Например, программы на Kotlin компилируются с помощью kotlinc в class-файлы, а затем подаются на вход JVM.
Как соотносятся JDK и Open JDK
Java Development Kit (JDK) — это комплект инструментов для разработки приложений на Java. В него входят несколько компонентов, которые позволяют разрабатывать и запускать приложения:
- Javас. Это компилятор, который преобразует исходники Java в class-файлы или формат jar.
- JVM. Виртуальная машина, которая исполняет байт-код.
- Стандартная библиотека. Набор модулей, классов, объектов и функций, которые доступны в языке.
- Документация. В ней содержится справочная информация об инструментах данной версии JDK.
Когда появляется новая версия языка, все эти компоненты обновляются.
В случае стандартной JVM (например, HotSpot) запуск Java-приложения выглядит так: сначала с помощью javac вы компилируете исходный код в class-файлы (или jar-файлы), и именно их вы можете поставлять в качестве приложения.
Чтобы приложение запустилось на хосте, там должна быть установлена виртуальная машина. Тогда пользователь пишет в командной строке: java -jar имя вашего jar-файла> — и программа запускается.
С нашей виртуальной машиной сценарий запуска приложения был другой: мы заранее компилировали class-файлы в один исполняемый exe-файл. Поэтому он работал на компьютере пользователя без каких-либо предустановленных JVM. Но, по сути, JVM никуда не исчезла — просто все её части были слинкованы в один экзешник.
В спецификации Java Virtual Machine почти ничего не сказано о том, как именно её реализовывать — только что должно получиться на выходе. Например, вы не можете явно освободить память из под объекта, когда он вам уже не нужен. Этим занимается специальный компонент JVM — Garbage Collector. Но вот как именно он работает, в спецификации не сказано.
Так и было задумано: спецификация позволяет создавать разные JVM, реализации которых в чём-то отличаются, но при этом удовлетворяют требованиям спецификации. И это замечательно, пусть расцветают сто цветов! Такие различия в реализации дают разным виртуальным машинам особые конкурентные преимущества: у кого-то более крутой сборщик мусора, у кого-то быстрый стартап, а кто-то реализовал более мощные оптимизации в компиляторе.
Первую JVM, как и язык Java, разработали в компании Sun Microsystems. Когда Sun опубликовала спецификацию, Oracle стала работать над своей JRockit, а IBM — над OpenJ9. Наша Excelsior JET вышла в свет в 2000 году.
Изначально все JVM были закрытыми, но в 2006 году Sun опубликовала исходники своей JVM HotSpot и компилятора javac, а потом и стандартной библиотеки Java. Это дало старт проекту OpenJDK — полностью открытой реализации JDK. Через какое-то время Sun была поглощена корпорацией Oracle, но при этом проект OpenJDK никуда не делся и до сих пор остаётся главной open-source-площадкой для разработки Java и JVM.
OpenJDK — это эталонная реализация, на которую ориентируются разработчики других виртуальных машин. Проект распространяется под GPL 2 + Classpath Exception, благодаря чему любая компания или разработчик, которым хватит квалификации, смогут форкнуть OpenJDK и начать разрабатывать свою собственную JVM. Конечно же, по условию лицензии их реализация тоже будет open source.
Существуют и реализации JVM, которые никак не связаны с OpenJDK. Ведь не только Sun Microsystems и Oracle создавали JVM. Другой пример — это IBM J9, которая, кстати, тоже открыла исходный код и стала называться OpenJ9.
Некоторые компании продают свои виртуальные машины. Например, у Azul есть свободная сборка Zulu и закрытая коммерческая Azul Zing. В последней есть уникальный сборщик мусора C4, который гарантировал низкие паузы ещё до того, как это стало мейнстримом. А также технология ReadyNow!, которая позволяет «запомнить» список всех оптимизаций кода и «проиграть» его на старте JVM, выводя машину на пиковую производительность.
Excelsior JET тоже была закрытой и платной. Она обеспечивала быстрый стартап, низкое потребление памяти и хорошую пиковую производительность во многих сценариях. Всё это мы получали за счёт статической компиляции, в отличие от динамической компиляции на лету в HotSpot.
Однако сегодня люди чаще пользуются бесплатными сборками, основанными на OpenJDK. Существуют как стандартные сборки OpenJDK от Oracle, так и сборки от других компаний и разработчиков, имеющих отношение к разработке OpenJDK (зачастую их публикуют контрибьюторы в OpenJDK не из Oracle).
В таких сборках могут быть дополнительные фичи, не включённые по умолчанию в стандартные сборки от Oracle. Либо такие альтернативные сборки прошли дополнительную сертификацию, например для использования с «КриптоПро». При этом такие сторонние билды проходят все стандартные тесты, поэтому гарантируется, что ваши программы будут работать как надо и пользоваться ими можно абсолютно безопасно и бесплатно.
Некоторые компании не только выкладывают свои билды, но и оказывают платную поддержку пользователям. Допустим, возникла проблема с виртуальной машиной: ваше приложение работает неожиданно медленно или даже крашится! Всякое бывает, ведь JVM — это тоже программа, в которой могут быть свои баги. Тогда инженеры этой компании оперативно разберутся в проблеме и решат её.
В целом вариантов виртуальных машин и их сборок очень много — в рамках этой статьи все не перечислить. Есть сборки от Oracle, Red Hat, Azul, IBM, BellSoft, Amazon и Microsoft. Сообщество Java-чемпионов написало замечательный документ, в котором перечислило все варианты и в целом разъяснило ситуацию с многообразием JVM и их сборок. Документ называется Java Is Still Free, рекомендую его всем к прочтению.
Как и зачем другие языки переходят на JVM
Java — это не просто язык, а целая философия. И она оказалась настолько востребованной, что у других языков программирования стали появляться реализации под JVM. Например, Jython и JRuby.
Главная причина появления таких реализаций — перформанс. За 25 лет человечество научилось делать хорошо оптимизированные JVM. Так почему бы за счёт этого не повысить производительность программ на Python и Ruby?
С другой стороны, так можно получить хорошую связь с экосистемой Java. Если мы запускаем код на JVM, он лучше взаимодействует с другими модулями на JVM. Значит, можно пользоваться и Java-библиотеками.
У Kotlin немного другая история. Когда язык только появился, было решено компилировать его в байт-код Java и запускать на JVM. Таким образом, реализация языка заключалась в написании хорошего транслятора — kotlinc — из исходного кода .kt в class-файлы. А реализация низкоуровневых компонентов типа сборщиков мусора или взаимодействия с операционной системой делегировалась уже существующим JVM.
Относительно недавно создатели Kotlin сделали Kotlin Native — технологию компиляции Kotlin в нативный код напрямую, без JVM. В нём низкоуровневые компоненты, такие как менеджер памяти, уже реализованы самостоятельно.
Хотя на словах кажется, что любой язык программирования легко перевести на JVM (достаточно написать транслятор в class-файлы), на деле всё оказывается намного сложнее. Грамотно отобразить фичи языка в байт-код Java и при этом получить хорошую производительность — нетривиальная задача. Посмотрите хотя бы на JRuby.
Чарльз Наттер часто делится опытом поддержки различных фич Ruby в проекте JRuby и рассказывает о сложностях, с которыми сталкивается. Чем дальше исходный язык от Java, тем сложнее задача трансляции. Но, думаю, всё возможно, и JRuby — наглядный тому пример.
Какие конкуренты есть у JVM
Самый известный конкурент Java Virtual Machine — платформа .NET и их виртуальная машина для реализации C#.
В начале 2000-х Microsoft делала свою виртуальную машину Java — Microsoft J++. Но из-за того, что корпорация не соблюдала спецификацию, Sun подала на неё судебный иск. Microsoft проиграла все суды и лишилась права делать виртуальную машину для Java. Есть мнение, что это стало одной из причин появления C#.
Java и C# решают одни и те же задачи и обладают одними и теми же преимуществами: строгая типизация, сборка мусора, безопасность — всё это совпадает. Это managed-языки широкого применения.
Раньше между платформами была одна принципиальная разница: Java был кроссплатформенным, а .NET и C# работали только на Windows. Но с тех пор, как появился .NET Core, C# тоже стал мультиплатформенным.
Отмечу, что сами языки Java и C# довольно разные, и C# развивается быстрее: там регулярно появляются интересные фичи, которые в Java приходят с большим опозданием или не приходят вообще. Поэтому как язык C# в целом выглядит интереснее.
Зато у Java мощная реализация и хорошо оптимизированные виртуальные машины. Это стало возможным благодаря «гонке вооружений» между разработчиками виртуальных машин. Вендоры на протяжении 20 лет соревновались, кто сделает самую крутую оптимизацию, лучший алгоритм сборки мусора, более быстрый стартап и так далее. Поэтому по многим показателям реализация Java выглядит куда лучше C#. Некоторые вещи, которые уже давно есть в JVM, только-только появляются в .NET.
Есть и другие языки, которые претендуют на роль конкурента Java, но они отличаются гораздо сильнее. Например, Python, который недавно занял 1-е место в рейтинге TIOBE. Он популярен в Data Science, AI, машинном обучении, скриптах и так далее. К сожалению, динамическая типизация не позволяет держать на нём слишком большую кодовую базу.
Ещё есть безумно популярный JavaScript, но его интересы с Java не очень пересекаются, так как сегодня Java во фронтенде не используется. Хотя когда-то были и такие планы (привет устаревшей технологии Java-апплетов).
Где Java хорош, а где — нет
Java широко используют в бэкенде, то есть во всех приложениях, которые работают на стороне сервера. Его главный конкурент — C#, но Java всё-таки значительно лидирует, потому что считается более кроссплатформенным. Хотя последнее уже не совсем правда. Также стоит отметить, что у Java банально есть фора по времени по сравнению с C#. Он появился на 10 лет раньше, поэтому успел захватить умы разработчиков и кодовые базы.
Почему Java, а не «швейцарский нож» С++? Просто Java удобнее и безопаснее для жизни, или, как принято говорить, не даст выстрелить себе в ногу. Разработчику не нужно думать об управлении памятью и сегфолтах, которые могу прилететь хоть откуда. Поэтому, когда дело касается будничных задач бэкенда, скорость разработки на Java и C# гораздо выше, чем на C++.
Java плохо подходит для приложений, которым требуется высокая производительность и гарантированное время отклика. Тем не менее некоторые пишут на Java и такие программы, если готовы мириться с небольшими задержками в микросекунды. Для них выигрыш от скорости разработки и надёжности важнее. Но писать на Java программное обеспечение для кардиостимуляторов, где все элементы должны работать точно, как швейцарские часы, — не стоит.

С другой стороны, приложения для трейдинга всё чаще пишут именно на Java. Казалось бы, где, если не в трейдинге, важен быстрый отклик — чтобы не потерять миллионы из-за скачка цен на акции Tesla? Однако на практике надёжность здесь важнее скорости: лучше торговать медленнее, но спокойно и надёжно, чем написать на С++ быструю биржу, которая через пять минут торгов крашнется. Java гарантирует безопасность, и это круто.
Что не так с JVM
В истории развития любого языка программирования всегда находятся тонкие места или сомнительные решения. Java здесь не исключение, встречаются такие спорные вопросы и в спецификациях Java и JVM.
Система модулей
Одна из спорных тем — Project Jigsaw и система модулей, появившаяся в девятой версии Java. Создатели Java долго делали систему, которая позволяет разбивать Java-программу на отдельные логические составляющие — модули. Это дополнительный уровень абстракции над давно существующими packages в Java.
На неё потратили много времени — ведь нужно было организовать поддержку в самом языке, виртуальной машине и других частях JDK. Система долго не попадала в релизную версию, а когда всё-таки попала, оказалась, мягко говоря, не слишком востребованной пользователями.
Как в языке появляются новые фичи и спецификации? Есть специальный совет Java Community Process (JCP), который рассматривает предложения Java Specification Request (JSR) и голосует за или против. В этом совете есть представители крупных компаний, есть представители user group и даже отдельные люди — в общем, представлены интересы разных сторон Java Community.
Идея новой модульной системы в Java была несколько раз отвергнута JCP (что вообще случается довольно редко), но всё-таки вошла в язык после значительных доработок и послаблений. Тем не менее спустя несколько лет мы видим, что идея так и не пришлась по вкусу Java-разработчикам и модулями пользуются редко.
Дженерики
Дженерики в Java, в отличие от многих других языков, — стираемые. Это означает, что все типовые параметры стираются через javac до Object. В рантайме вы не сможете понять, какой тип вам на самом деле пришёл. У этого подхода есть свои плюсы и минусы, а споры о том, что лучше — стираемые или нестираемые дженерики — продолжаются и по сей день. Тем не менее, выбор в пользу стираемых дженериков в Java сделан не случайно. Подробное обоснование, почему дженерики в Java такие, можно почитать вот в этой статье Брайана Гетца «Background: how we got the generics we have».
Но как бы вы не относились к реализации дженериков в Java, сейчас есть существенная проблема: нельзя использовать примитивные типы в качестве типовых параметров (ведь они несовместимы с Object). Это сокращает выразительную силу языка и вынуждает либо использовать Boxed-типы (что может ухудшить производительность), либо и вовсе специализировать функции под примитивные типы вручную. Исправить это собираются с помощью специализированных дженериков в рамках проекта Valhalla.
Обратная совместимость
Обратная совместимость — один из главных принципов Java, которым совет JCP не пожертвует даже ради самой передовой фичи. От некоторых вещей иногда отказываются, но при этом старый код всё равно должен продолжать работать.
Например, реализация исключений через инструкции JSR/RET встречается в старом байт-коде, а в новом — нет. Но до сих пор во всех тулах нужно уметь поддерживать старый байт-код ради библиотеки, написанной 20 лет назад, но которая так и продолжает использоваться в современных проектах в виде того же старого формата .jar.
С одной стороны, этот принцип позволяет построить стабильную экосистему. Бизнес может не бояться, что выйдет новая версия, которая всё сломает и навсегда заблокирует путь к обновлению. С другой стороны, это тормозит инновации. Возможно, Java развивается медленнее, чем C#, потому, что у нас обратная совместимость — это священная корова, которую нельзя трогать.
Насколько глубоко разработчику нужно знать JVM
На самом деле это очень холиварный вопрос. В основном ответ на него зависит от задач, которые хочет решать джавист.
Думаю, 30% программистов могут спокойно работать и не понимать, что происходит внутри виртуальной машины. Другим 50% достаточно на среднем уровне знать, как устроена JVM, — тогда они будут отличными мидлами и сеньорами. Их работа не в том, чтобы копаться в кишках виртуальной машины, но некоторые знания о её устройстве помогут им писать более эффективный код и избежать многих ошибок. В оставшихся 20% задач без знания деталей всё-таки не обойтись. Получается, чем лучше вы разбираетесь в виртуальной машине, тем более широкий класс задач способны решать.

Если в проекте важна производительность и повысить её с помощью выбора более оптимального алгоритма нельзя, надо разбираться, как работает сборщик мусора и как повысить его эффективность, какие настройки можно поменять, что такое деоптимизация, почему она происходит и так далее.
Java-разработчик, который регулярно погружается в эту тему, со временем сможет стать Performance Engineer. Эти специалисты находят проблемы производительности, анализируют глубинные процессы в JVM и исправляют их. Они решают проблемы не дописыванием кода в виртуальную машину, а настраивают её, как часовщики.
С точки зрения культуры всем разработчикам на managed-языках полезно знать, что происходит под капотом машины, когда они нажимают кнопку Run в IDE. Конечно, не нужно запоминать, что и в какой момент делает каждая деталь JVM. Но пройти вводный курс и понять на концептуальном уровне, что такое интерпретатор, Just In Time Compiler, что значит «умер объект» и так далее, — полезно.
Разработчик, который не знает ответов на все эти вопросы, способен решить довольно много задач. Но однажды он столкнётся с ошибками, причины которых даже не сможет понять. Например, если не задумываться, откуда берётся память и как она возвращается операционной системе, то можно получить от IDE сообщение Out of memory. А всё потому, что программа потребляет слишком много памяти. Разработчик, который знает, как устроена память, постарается оптимизировать код и не создавать горы объектов.
Куда развивается JVM
Сейчас довольно активно развиваются три проекта, которые рано или поздно войдут в новые версии Java.
Loom
Loom — это проект по добавлению виртуальных тредов в Java. С ним треды не мапятся на треды операционной системы, а живут сами по себе. И лишь когда их нужно исполнить, они будут садиться на треды операционки.
Раньше каждому экземпляру класса java.lang.Thread (через которые реализуется многопоточное исполнение) соответствовал один поток операционной системы. Вполне логичное решение, но есть проблема: потоков операционной системы не слишком много, поэтому вряд ли у вас получится создать больше нескольких тысяч потоков, реализованных таким образом. Project Loom предлагает альтернативу — виртуальные потоки, которые уже не связаны соотношением 1 к 1 с потоками виртуальной системы. Вместо этого они время от времени садятся на эти OS threads, чтобы выполнить очередной квант работы.
Идея не новая. Например, в Go так было всегда. Да и вообще о виртуальных тредах говорили уже много десятилетий. И даже в самом Java в 1990-е были грин-треды — схожая идея, где N зелёных потоков назначались на один поток операционной системы (тогда в процессорах было по одному ядру и проблема легковесной многопоточности не стояла так остро). Можно сказать, что Loom — это в некотором смысле реинкарнация зелёных тредов, но сделанная на более серьёзном уровне.
Этот проект очень важен, так как в современном мире микросервисов и серверов с огромным количеством одновременных подключений вам часто хотелось бы создавать десятки и сотни тысяч тредов. Со старым подходом к реализации через OS threads это просто невозможно, а вот с Loom всё получится.
Panama
Panama — это проект, посвящённый взаимодействию между Java и нативным кодом, написанным, например, на C или C++. Конечно, Java мог взаимодействовать с нативным кодом с самого рождения. Основное решение в этой области — Java Native Interface, очень мощный, но медленный и неудобный в использовании механизм. Чтобы взаимодействовать с нативами, приходилось писать некрасивый, громоздкий и, что самое главное, небезопасный код. Я уверен, что любому джависту, который хоть что-нибудь делал с JNI, как минимум не понравилось, а как максимум — он до сих видит кошмары про развалы в JNI.
Чтобы избавить Java-разработчиков от ночных кошмаров, авторы Panama уже много лет работают над своим проектом, который, как Панамский канал, соединяет два мира: нативный и Java. Panama предлагает новый интерфейс и его оптимизированную реализацию на стороне JVM, которая позволит приятно и безопасно работать с нативным кодом, в том числе с off-heap .
Valhalla
Проект Valhalla посвящён введению в Java новых типов объектов, так называемых value-типов, или inline-типов, или же primitive-value-типов — это текущее название. Да, проект настолько сложный, что даже основная его концепция часто меняет имя!
Если коротко, то смысл в том, чтобы выделить подкласс объектов, у которых нет identity. Что это такое? В Java вы можете создать два абсолютно одинаковых объекта с помощью оператора new. Потом сравнить их на == и получить false. Это разные объекты! Они сравниваются не по содержимому (которое одинаковое), а по некоторому уникальному свойству, назначаемому каждому объекту при создании. Вот возможность сравнивать не по содержимому, а по чему-то ещё — это и есть identity.
С другой стороны, можно объявить две переменные типа int, записать в каждую из них значение 42, сравнить на == и получить результат true. Всё потому, что у int никакого identity нет, они сравниваются по содержимому.
Цель Valhalla — дать пользователям возможность самим описывать классы, у которых нет identity, и подготовить к этому уже существующую типовую систему. Как следствие, можно будет, например, заводить плоские поля таких типов внутри других классов (то есть фактически инлайнить их поля внутрь других объектов), работать с плоскими массивами таких объектов и даже получить специализированные дженерики.
Это огромное, фундаментальное изменение всей платформы Java, за которым очень интересно следить и которого стоит ожидать, ведь оно принесёт множество возможностей обычным разработчикам.
На каких языках разрабатывают JVM и библиотеки для Java
Сами виртуальные машины Java обычно пишут на С++, стандартная библиотека же в основном написана на самом Java (хотя иногда и приходится уходить в нативный код, то есть снова в плюсы). Вообще, так повелось, что системщину пишут на плюсах, ведь здесь, с одной стороны, важна производительность, а с другой — связь с низким уровнем, с операционной системой и железом. В то же время стало очевидно, что далеко не все компоненты виртуальной машины обязательно нужно писать на С++. Например, зачем делать компилятор на С++, если есть замечательные managed-языки вроде Java или Scala?
Вот, например, в Oracle Labs разрабатывает проект GraalVM. Он состоит из трёх компонентов:
- КомпиляторGraal — мощный оптимизирующий компилятор, в будущем он, возможно, заменит компилятор C2 из HotSpot. Он не уступает по качеству многих оптимизаций, но написан полностью на Java.
- Truffle Framework — специальный фреймворк для написания интерпретаторов других языков, которые потом запускаются на GraalVM. По сути, это быстрый способ реализовать любой язык программирования на базе GraalVM! Опять-таки, интерпретаторы пишутся на managed-языках.
- Graal Native Image — отдельный режим сборки приложений, который на самом деле представляет из себя целую виртуальную машину, но написанную с некоторыми нарушениями спецификации. Зато она позволяет получить быстрый стартап и низкое потребление памяти. Рантайм для такой виртуальной машины тоже частично написан на Java! Понятно, что не полностью и с разными ограничениями языка (на самом деле там используется отдельный диалект — System Java), но тем не менее это возможно.
Вообще, писать виртуальные машины на managed-языках — давняя мечта системщиков. Ведь, например, компилятор С написан на С? Вот и разработчики виртуальных машин для managed-языков хотят писать их на Java или других managed-языках, а не на опасном и болезненном С++.
Как контрибьютить в OpenJDK
Для начала скажу, что я никогда не контрибьютил в OpenJDK, а занимался разработкой другой, проприетарной и закрытой JVM. Поэтому о процедуре коммита в OpenJDK имею только смутное представление, так что написанному ниже доверяйте на свой страх и риск!
Если бы я задался целью контрибьютить в OpenJDK, то думал бы в двух направлениях:
- Найти что-то небольшое, что получится исправить или улучшить. Это может быть несложный (и низкоприоритетный) баг в баг-трекере OpenJDK или неэффективность какого-нибудь алгоритма в платформенных классах. Исправьте эту проблему, соберите OpenJDK и проверьте, что, например, алгоритм и правда стал работать лучше на каких-нибудь бенчмарках.
Потом напишите в мейлинг-лист, расскажите о сути улучшения и попросите сделать ревью. Наконец, пройдите его, а затем и остальную процедуру коммита. Насколько я знаю, она довольно стандартная, ведь OpenJDK теперь находится на GitHub. Поздравляю, теперь вы контрибьютор в OpenJDK!
По рассказам людей, которые прошли по этому пути, вся процедура может занять довольно много времени, особенно в первый раз, но в целом это вполне реально.
- Устроиться на работу в компанию-контрибьютор. В этом случае вы будете разрабатывать код, который попадёт в OpenJDK, в рабочее время. Однако сложность в том, что таких компаний всё-таки очень мало. Зато попасть в одну из них — действительно круто. Яркий пример такой компании — питерская BellSoft, которая в прошлом году заняла четвёртое место в мире (!) среди внешних (не из Oracle) контрибьюторов в OpenJDK.
На кого подписаться и где следить за новостями JVM
Разработчики виртуальных машин регулярно улучшают свои VM и зачастую делятся новостями о разработке и состоянии тех или иных проектов в рамках OpenJDK и не только. Черпать актуальную информацию можно из мейлинг-листов, конференций и Twitter.
Мейлинг-листы
Мейлинг-лист — это такой почтовый ящик, на который можно подписаться. Подписчики мейлинг-листа получают письма из общей рассылки, но ещё могут отвечать, участвовать в дискуссиях или задавать вопросы. Именно так и общаются разработчики многих языков программирования.
Мейлинг-листов про Java и JVM довольно много, есть свои мейлинг-листы для разных компонентов JDK и разных подпроектов в OpenJDK. Например, есть отдельные мейлинг-листы для упомянутых выше проектов Loom или Valhalla. Так что тут главное — выбрать темы, которые вам интересны, а потом найти соответствующие мейлинг-листы на сайте сообщества Java.
Новые предложения по технологии в первую очередь пишут и обсуждают именно в мейлинг-листах, поэтому в них отражается история развития Java и JVM. Такой канал связи действительно работает, хоть и может показаться немного устаревшим. Если хотите узнать сложные детали, например как работает конкретная часть виртуальной машины, советую подписаться на соответствующий мейлинг-лист.
Конференции
Более привычный и простой для восприятия источник информации — конференции. Разработчики JVM регулярно выступают с докладами, в которых по косточкам разбирают детали реализации, при этом в доступной и понятной форме.
Наибольшая концентрация знаний — на ежегодной конференции Java Virtual Machine Language Summit. Видео выступлений можно посмотреть на YouTube-канале Java. Очень много хардкорных и качественных докладов от разработчиков JVM есть на российских конференциях Joker и JPoint от компании JUG Ru Group.
Сами мы (JUGNsk) тоже организуем свою Java-конференцию SnowOne в Новосибирске. В нашем программном комитете много системщиков, поэтому докладам о внутренностях виртуальных машин на конференции уделяется особое внимание.
Twitter
Ещё один источник свежей информации — Twitter. Часто там появляются последние новости о Java вообще и JVM в частности. Из англоязычных авторов советую подписаться на аккаунты Брайана Гетца и Марка Рейнхольда — архитекторов языка Java и Java-платформы.
В России тоже есть суперзвёзды и разработчики JVM, например Алексей Шипилёв. Он один из главных контрибьюторов Shenandoah GC, работал в Oracle, а сейчас — в Red Hat. При этом он пишет классные посты (чего стоит одна только серия JVM Anatomy Quarks!) и выступает с отличными докладами о том, как устроена JVM изнутри.
Ещё всегда интересно читать Сергея Куксенко — перформанс-инженера в Oracle. Он разгоняет многие фичи, которые появляются в Java, и интересно об этом рассказывает. А новости о HotSpot и Panama можно найти в аккаунте Владимира Иванова.
В целом в Twitter есть ещё огромное количество как русскоязычных, так и англоязычных крутых инженеров, связанных с разработкой JVM. Так что принцип здесь такой же, как с мейлинг-листами: находите человека, участвующего в определённом проекте в OpenJDK (или за его пределами), и смело подписываетесь!
Резюме:
- Чтобы решать рутинные задачи, джависту не нужно разбираться в деталях JVM. Но перейти на следующий уровень не получится, если хотя бы на концептуальном уровне не понимать, как работает интерпретатор, что такое Just In Time Compilation, как устроена память и так далее.
- JDK — это комплект инструментов Java-разработчика. В него входит: javac, сама виртуальная машина, стандартная библиотека классов и документация. OpenJDK — это эталонная версия JDK с полностью открытым исходным кодом. Основные контрибьюторы в этот проект — это Oracle, но кроме неё есть и много других компаний и разработчиков, которые вносят свой вклад.
- Обычно виртуальные машины пишут на языках C/C++. Но уже есть проекты, в которых JVM, компилятор и рантайм почти полностью написаны на Java или его диалекте.
- Контрибьютить в OpenJDK может любой желающий, но серьёзные изменения в JVM обычно вносят опытные разработчики. Тем не менее возможно найти себе небольшие задачи, с которых и начать этот путь.
Читайте также:
- Чем Rust отличается от плюсов: откровение ветерана C++
- Есть ли место творчеству в программировании: подборка мнений опытных разработчиков
- Дженерики в Java для тех, кто постарше: стирание типов, наследование и принцип PECS
