Что такое JVM? Знакомство с виртуальной машиной Java

Java virtual machine (JVM) — это программа, предназначенная для выполнения других программ. В ее основу заложена простая идея, которая всегда будет одним из величайших примеров кодирования в стиле «kung fu».
Для чего используется JVM
JVM имеет две основные функции:
  1. Позволяет запускать Java-приложения на любых устройствах или операционных системах (принцип — «Написал один раз, запускай везде»)
  2. Управляет и оптимизирует память, используемую приложением
В 1995 году, когда Java появилась, все компьютерные программы были написаны под определенные операционные системы, и управлять памятью приходилось разработчику программного обеспечения. Так что появление JVM было революцией.
Рисунок 1: Общее представление JVM
Существует техническое определение JVM, а также его повседневная формулировка:
    • Техническое определение: JVM — это спецификация программного обеспечения, которое выполняет код и предоставляет среду выполнения для этого кода
    • Повседневная формулировка: JVM — это способ запуска наших Java-приложений. Мы настраиваем параметры JVM, а затем полагаемся на ее автоматическое управление ресурсами программы во время выполнения
    Когда разработчики говорят о JVM, обычно имеют в виду процесс, запущенный на устройстве, который предоставляет и контролирует использование ресурсов Java-приложения. Спецификация JVM описывает требования для разработки программы, которая выполняет эти задачи.
    Сборка мусора
    До Java память программы контролировалась программистом. В Java же памятью управляет виртуальная машина через процесс, называемый сборкой мусора, который непрерывно определяет и устраняет неиспользуемую память в программах. Сборка мусора происходит внутри работающей JVM.
    В ранний период Java подвергалась критике, так как не была «Close to the metal» как C++ и поэтому не была такой быстрой. Особенно спорным был процесс сборки мусора. С тех пор были предложены и использованы различные алгоритмы и подходы, которые значительно улучшили сборку мусора.
    Три части JVM
    Глобально JVM состоит из трех частей: спецификация, реализация и экземпляр. Рассмотрим каждую из них.
    1. Спецификация JVM
    Первая часть JVM — спецификация в которой не определены детали реализации JVM, что обеспечивает максимальную свободу творчества при ее создании:
    «Для правильной реализации виртуальной машины Java, вам лишь необходимо уметь читать class-файлы и правильно выполнять указанные в нем операции»
    Себастьян Бах однажды писал о создании музыки похожим образом:
    «Все что вам нужно делать, это нажимать нужную клавишу в нужное время»
    Таким образом, все что JVM должна делать — это корректно запускать Java-программы. Звучит просто, но это колоссальная задача, особенно, если учитывать мощь и гибкость языка Java.
    2. Реализация JVM
    Существует множество различных реализаций спецификации JVM как коммерческих, так и с открытым исходным кодом. JVM HotSpot от проекта OpenJDK является эталонной реализацией и содержит одну из наиболее тщательно проверенных в мире кодовых баз. HotSpot также является самой широко используемой JVM.
    Почти все лицензированные JVM созданы, как ответвление от OpenJDK и HotSpot JVM, включая лицензионный JDK от Oracle. Разработчики, создающие лицензированные продукты на основе OpenJDK, зачастую мотивируются желанием увеличить производительность для определенных операционных систем. Обычно пользователи загружают и устанавливают JVM, как часть среды выполнения Java (JRE).
    3. Экземпляр JVM
    После того как спецификация JVM реализована и выпущена, вы можете загрузить ее как приложение. Загруженная программа является экземпляром виртуальной машины.
    В большинстве случаев, говоря о JVM, имеют в виду экземпляр JVM, который работает в среде разработки. Вы можете сказать: «Привет Макс, сколько памяти использует JVM на этом сервере?» или «Я не могу поверить, я сделал зацикленный вызов, и переполнение стека сломало мою JVM. Ошибка новичка!»
    Загрузка и выполнение class-файлов в JVM
    Мы говорили о роли JVM в запуске Java-приложений, но как она выполняет свою функцию? При выполнении Java-приложений JVM зависит от загрузчика классов и механизма выполнения.
    Загрузчик классов в JVM
    Все в Java является классом, и все Java-приложения состоят из классов. Приложение может состоять из одного или тысячи классов. Для запуска приложения JVM должна загрузить скомпилированные .class-файлы в контекст, такой как сервер, где они будут доступны. JVM зависит от своего загрузчика класса во время выполнения этой функции.
    Загрузчик классов Java является частью JVM, которая загружает классы в память и делает их доступными для выполнения. Загрузчики классов используют технику ленивой загрузки (lazy-loading) и кэширования, чтобы сделать загрузку классов максимально эффективной.
    Любая виртуальная машина Java включает в себя загрузчик классов. Спецификация JVM описывает стандартные методы для запросов и управления загрузчиком во время работы, но за выполнение этих возможностей отвечает конкретная реализация JVM.
    Механизм выполнения в JVM
    Как только загрузчик классов выполнил свою работу, JVM начинает выполнять код каждого класса.
    Выполнение кода включает управление доступом к системным ресурсам. Механизм выполнения JVM стоит между работой программы, с ее запросами на файловые, сетевые ресурсы и ресурсы памяти, и операционной системой, которая обеспечивает эти ресурсы.
    Управление системными ресурсами
    Системные ресурсы могут быть разделены на две больших категории: память и все остальное.
    Вспомните, что JVM отвечает за очистку неиспользуемой памяти, а сборщик мусора — это механизм, который эту очистку осуществляет. JVM также отвечает за распределение и поддержание ссылочной структуры, которую разработчик принимает как должное. Например, при использовании ключевого слова new, механизм выполнения JVM осуществляет запрос к операционной системе на выделение памяти.
    Помимо памяти, механизм выполнения управляет ресурсами файловой системы и сети. Так как JVM может взаимодействовать с разными операционными системами, это задача не из легких. В дополнение к потребностям каждого приложения в ресурсах, механизм выполнения должен корректно работать с каждой операционной системой.
    Эволюция JVM: прошлое, настоящее, будущее
    В 1995 году JVM представила две революционных концепции, которые с тех пор стали стандартом в современной разработке: «Написал один раз, запускай везде» и автоматическое управление памятью. В то время совместимость ПО была смелой концепцией, но сейчас это незаменимое удобство. Точно так же, в то время разработчики должны были сами управлять программной памятью, нынешнее поколение живет с автоматической сборкой мусора.
    Изначально виртуальная машина Java предназначалась только для Java, но сегодня она может поддерживать разные скриптовые и другие языки программирования, включая Scala, Groovy и Kotlin. Глядя вперед, трудно увидеть будущее, в котором JVM не является заметной частью развития разработки программного обеспечения.
    Оцените статью, если она вам понравилась!