Виртуальная машина Java - Java virtual machine

Виртуальная машина Java
ДизайнерSun Microsystems
Биты32-битный
Введено1994
Версия14.0.1[1]
ТипКуча и регистрация – регистрация
КодированиеПеременная
РазветвлениеСравните и разделите
Порядок байтовБольшой
Открытьда
Регистры
Общее назначениеСтек операндов для каждого метода (до 65535 операндов) плюс локальные переменные для каждого метода (до 65535)
Обзор архитектуры виртуальной машины Java (JVM) на основе спецификации виртуальной машины Java Java SE 7 Edition

А Виртуальная машина Java (JVM) это виртуальная машина что позволяет компьютеру работать Ява программы, а также программы, написанные на Другие языки которые также скомпилированы в Байт-код Java. JVM подробно описывается Технические характеристики это формально описывает, что требуется в реализации JVM. Наличие спецификации гарантирует совместимость программ Java в различных реализациях, так что авторы программ, использующие Комплект для разработки Java (JDK) не нужно беспокоиться об особенностях базовой аппаратной платформы.

JVM эталонная реализация разработан OpenJDK проект как Открытый исходный код код и включает JIT-компилятор называется HotSpot. Коммерчески поддерживаемые выпуски Java доступны по адресу Корпорация Oracle основаны на среде выполнения OpenJDK. Затмение OpenJ9 - еще одна JVM с открытым исходным кодом для OpenJDK.

Спецификация JVM

Виртуальная машина Java - это абстрактный (виртуальный) компьютер, определенный в спецификации. Используемый алгоритм сборки мусора и какая-либо внутренняя оптимизация инструкций виртуальной машины Java (их перевод в машинный код) не указаны. Основная причина этого упущения - не ограничивать разработчиков без необходимости. Любое приложение Java может быть запущено только внутри некоторой конкретной реализации абстрактной спецификации виртуальной машины Java.[2]

Начиная с Платформа Java, стандартная версия (J2SE) 5.0 изменения в спецификации JVM были разработаны под Процесс сообщества Java как JSR 924.[3] По состоянию на 2006 г., изменения в спецификации для поддержки изменений, предложенных в формат файла класса (JSR 202)[4] выполняются как поддерживаемый выпуск JSR 924. Спецификация JVM была опубликована как синяя книга,[5] В предисловии говорится:

Мы намереваются, что эта спецификация должна достаточно документировать виртуальную машину Java, чтобы сделать возможными совместимые реализации чистой комнаты. Oracle предоставляет тесты, которые проверяют правильность работы реализаций виртуальной машины Java.

Одна из JVM Oracle называется HotSpot, другой, унаследованный от BEA Systems является JRockit. Чистая комната Реализации Java включают Каффе, OpenJ9 и CEE-J Скельмира. Oracle владеет товарным знаком Java и может разрешить его использование для сертификации комплектов реализации как полностью совместимых со спецификацией Oracle.

Загрузчик классов

Одна из организационных единиц байт-кода JVM - это класс. Реализация загрузчика классов должна уметь распознавать и загружать все, что соответствует формату файла классов Java. Любая реализация может свободно распознавать другие двоичные формы, кроме учебный класс файлы, но он должен распознавать учебный класс файлы.

Загрузчик классов выполняет три основных действия в этом строгом порядке:

  1. Загрузка: находит и импортирует двоичные данные для типа
  2. Связывание: выполняет проверку, подготовку и (необязательно) разрешение
    • Проверка: обеспечивает правильность импортированного типа
    • Подготовка: выделяет память для переменных класса и инициализирует память значениями по умолчанию
    • Разрешение: преобразует символьные ссылки из типа в прямые ссылки.
  3. Инициализация: вызывает код Java, который инициализирует переменные класса их правильными начальными значениями.

В общем, существует два типа загрузчика классов: загрузчик классов начальной загрузки и пользовательский загрузчик классов.

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

Архитектура виртуальной машины

JVM работает с примитивными значениями (целыми числами и числами с плавающей запятой) и Рекомендации. По сути, JVM - это 32-битная машина. длинный и двойной типы, которые являются 64-битными, поддерживаются изначально, но занимают две единицы памяти в локальных переменных кадра или стеке операндов, поскольку каждая единица имеет 32 бита. логический, байт, короткая, и char типы все знак расширенный (Кроме char который с нулевым расширением ) и работает как 32-битные целые числа, как и int типы. У меньших типов есть только несколько инструкций по загрузке, сохранению и преобразованию типов. логический работает как 8-битный байт значения, где 0 представляет ложный и 1, представляющий истинный. (Несмотря на то что логический рассматривается как тип, так как Спецификация виртуальной машины Java, второе издание прояснил эту проблему, в скомпилированном и исполняемом коде есть небольшая разница между логический и байт кроме искажение имени в сигнатуры методов и тип логических массивов. логическийs в сигнатурах методов искажаются как Z пока байтs искажены как B. Булевы массивы несут тип логическое [] но используйте 8 бит на элемент, а JVM не имеет встроенной возможности упаковывать логические значения в битовый массив, поэтому за исключением типа, который они выполняют и ведут себя так же, как байт массивы. Во всех других случаях логический тип фактически неизвестен JVM, поскольку все инструкции для работы с логическими значениями также используются для работы с байтс.)

JVM имеет сборщик мусора куча для хранения объектов и массивов. Код, константы и другие данные класса хранятся в «области метода». Область метода логически является частью кучи, но реализации могут обрабатывать область метода отдельно от кучи и, например, не могут собирать ее мусором. У каждого потока JVM также есть свой стек вызовов (для ясности называется «стек виртуальных машин Java»), в котором хранятся кадры. Новый фрейм создается каждый раз, когда вызывается метод, и фрейм уничтожается при выходе из этого метода.

Каждый фрейм предоставляет «стек операндов» и массив «локальных переменных». Стек операндов используется для операндов для вычислений и для получения возвращаемого значения вызываемого метода, в то время как локальные переменные служат той же цели, что и регистры а также используются для передачи аргументов метода. Таким образом, JVM является одновременно штабелеукладчик и зарегистрировать машину.

Инструкции по байт-коду

JVM имеет инструкции для следующих групп задач:

Цель - бинарная совместимость. Каждый конкретный хост Операционная система требуется собственная реализация JVM и среды выполнения. Эти JVM семантически интерпретируют байт-код одинаково, но фактическая реализация может отличаться. Более сложная, чем просто эмуляция байт-кода, - это совместная и эффективная реализация API ядра Java который должен быть сопоставлен с каждой операционной системой хоста.

Эти инструкции работают с набором общих абстрагированный типы данных скорее собственные типы данных любого конкретного архитектура набора команд.

Языки JVM

Язык JVM - это любой язык, функциональность которого может быть выражена в виде допустимого файла класса, который может быть размещен на виртуальной машине Java. Файл класса содержит инструкции виртуальной машины Java (Байт-код Java ) и таблицу символов, а также другую вспомогательную информацию. Формат файла класса - это независимый от оборудования и операционной системы двоичный формат, используемый для представления скомпилированных классов и интерфейсов.[6]

Существует несколько языков JVM, как старые языки, перенесенные на JVM, так и совершенно новые языки. JRuby и Jython пожалуй, самые известные порты существующих языков, т.е. Рубин и Python соответственно. Из новых языков, которые были созданы с нуля для компиляции в байт-код Java, Clojure, Apache Groovy, Scala и Котлин могут быть самыми популярными. Примечательной особенностью языков JVM является то, что они совместимы друг с другом, так что, например, библиотеки Scala можно использовать с программами Java и наоборот.[7]

Java 7 JVM реализует JSR 292: Поддержка языков с динамической типизацией[8] на платформе Java, новая функция, которая поддерживает динамически типизированные языки в JVM. Эта функция разработана в рамках Машина да Винчи проект, задачей которого является расширение JVM для поддержки языков, отличных от Java.[9][10]

Верификатор байт-кода

Основная философия Java заключается в том, что она по своей сути безопасна с точки зрения того, что никакая пользовательская программа не может вызвать сбой хост-машины или иным образом неуместно вмешиваться в другие операции на хост-машине, и что можно защитить определенные методы и структуры данных, принадлежащие доверенным код от доступа или повреждения ненадежным кодом, выполняемым в той же JVM. Кроме того, недопустимы распространенные ошибки программиста, которые часто приводят к повреждению данных или непредсказуемому поведению, например, доступ к концу массива или использование неинициализированного указателя. Несколько функций Java объединяются для обеспечения этой безопасности, включая модель классов, сборщик мусора. куча, и верификатор.

JVM проверяет весь байт-код перед его выполнением. Эта проверка состоит в основном из трех типов проверок:

  • Филиалы всегда в действующих местах
  • Данные всегда инициализируются, а ссылки всегда типобезопасны
  • Доступ к приватным или пакетным приватным данным и методам строго контролируется

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

Верификатор разрешает только некоторые последовательности байт-кода в допустимых программах, например а инструкция перехода (перехода) может нацеливаться только на инструкцию в том же метод. Кроме того, верификатор гарантирует, что любая данная инструкция работает в фиксированном месте стека,[11] позволяя JIT-компилятору преобразовывать доступ к стеку в доступ к фиксированному регистру. Из-за этого то, что JVM представляет собой стековую архитектуру, не подразумевает потери скорости для эмуляции на регистровые архитектуры при использовании JIT-компилятора. Перед лицом архитектуры JVM с проверкой кода для JIT-компилятора не имеет значения, получает ли он именованные мнимые регистры или мнимые позиции стека, которые должны быть выделены регистрам целевой архитектуры. Фактически, проверка кода отличает JVM от классической стековой архитектуры, эффективная эмуляция которой с помощью JIT-компилятора более сложна и обычно выполняется более медленным интерпретатором.

В исходной спецификации верификатора байт-кода использовался естественный язык, который в некоторых отношениях был неполным или неправильным. Был предпринят ряд попыток указать JVM как формальную систему. Таким образом можно более тщательно проанализировать безопасность текущих реализаций JVM и предотвратить возможные взломы. Также можно будет оптимизировать JVM, пропустив ненужные проверки безопасности, если будет доказано, что выполняемое приложение безопасно.[12]

Безопасное выполнение удаленного кода

Архитектура виртуальной машины позволяет очень точно контролировать действия, которые разрешено выполнять коду на машине. Он предполагает, что код "семантически" правильный, то есть успешно прошел (формальный) процесс проверки байт-кода, материализованный инструментом, возможно, за пределами виртуальной машины. Это разработано, чтобы обеспечить безопасное выполнение ненадежного кода из удаленных источников, модель, используемая Java-апплеты, и другие загрузки безопасного кода. После проверки байт-кода загруженный код запускается в ограниченном "песочница ", который предназначен для защиты пользователя от неправильного поведения или вредоносного кода. В дополнение к процессу проверки байт-кода издатели могут приобрести сертификат, с помощью которого цифровая подпись апплеты как безопасные, давая им разрешение попросить пользователя выйти из песочницы и получить доступ к локальной файловой системе, буфер обмена, выполнить внешние части программного обеспечения или сеть.

Формальное подтверждение верификаторов байт-кода было сделано в индустрии Javacard (формальная разработка встроенного верификатора для байт-кода карты Java.[13])

Интерпретатор байт-кода и своевременный компилятор

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

Когда байт-код Java выполняется интерпретатором, выполнение всегда будет медленнее, чем выполнение той же программы, скомпилированной на машинном языке. Эта проблема решается JIT-компиляторы для выполнения байт-кода Java. Компилятор JIT может переводить байт-код Java на собственный машинный язык во время выполнения программы. После этого переведенные части программы можно будет выполнить гораздо быстрее, чем их можно будет интерпретировать. Этот метод применяется к тем частям программы, которые часто выполняются. Таким образом, JIT-компилятор может значительно ускорить общее время выполнения.

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

Байт-код Java предназначен для обеспечения безопасности и независимости от платформы.[14] Некоторые реализации JVM не включают интерпретатор, а состоят только из оперативного компилятора.[15]

JVM в веб-браузере

В начале существования платформы Java JVM продавалась как веб-технология для создания Богатые Интернет-приложения. По состоянию на 2018 год, большинство веб-браузеров и операционные системы в комплекте веб-браузеры не поставляются с Java плагин, а также они не допускают боковой загрузки каких-либоВспышка плагин. Плагин для браузера Java устарел в JDK 9.[16]

В NPAPI Подключаемый модуль браузера Java был разработан, чтобы позволить JVM выполнять так называемые Java-апплеты встроены в HTML-страницы. Для браузеров с установленным подключаемым модулем апплету разрешено рисовать в прямоугольной области на назначенной ему странице. Поскольку подключаемый модуль включает JVM, апплеты Java не ограничиваются языком программирования Java; любой язык, предназначенный для JVM, может работать в подключаемом модуле. Ограниченный набор API-интерфейсов позволяет апплетам получать доступ к микрофону пользователя или к 3D-ускорению, хотя апплеты не могут изменять страницу за пределами ее прямоугольной области. Adobe Flash Player, основная конкурирующая технология, работает в этом отношении точно так же.

По состоянию на июнь 2015 г. согласно W3Techs, Java-апплет и Silverlight использование снизилось до 0,1% для всех веб-сайтов, а использование Flash упало до 10,8%.[17]

JVM и интерпретаторы JavaScript

По состоянию на май 2016 г. JavaPoly позволяет пользователям импортировать неизмененные библиотеки Java и вызывать их прямо из JavaScript. JavaPoly позволяет веб-сайтам использовать немодифицированные библиотеки Java, даже если на компьютере пользователя не установлена ​​Java.[18]

Компиляция в JavaScript

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

Компиляция байт-кода JVM, который является универсальным для языков JVM, позволяет использовать существующий компилятор языка для байт-кода. Основным байт-кодом JVM для компиляторов JavaScript является TeaVM,[19] компилятор, содержащийся в Dragome Web SDK,[20] Bck2Brwsr,[21] и j2js-компилятор.[22]

Ведущие компиляторы с языков JVM на JavaScript включают компилятор Java-to-JavaScript, содержащийся в Google Web Toolkit, Clojurescript (Clojure ), GrooScript (Apache Groovy ), Scala.js (Scala) и другие.[23]

Среда выполнения Java

Java Runtime Environment (JRE), выпущенная Oracle, представляет собой свободно доступный дистрибутив программного обеспечения, содержащий автономную JVM (HotSpot ), Java стандартная библиотека (Библиотека классов Java ), инструмент настройки и - до его прекращения в JDK 9 - подключаемый модуль браузера. Это наиболее распространенная среда Java, установленная на персональные компьютеры в ноутбуке и настольном компьютере фактор формы. Мобильные телефоны включая особенность телефонов и рано смартфоны поставляемые с JVM, скорее всего, будут включать JVM, предназначенную для запуска приложений, ориентированных на Micro Edition платформы Java. Между тем, большинство современных смартфонов, планшетные компьютеры, и другие карманные компьютеры которые запускают приложения Java, скорее всего, будут делать это благодаря поддержке Операционная система Android, который включает Открытый исходный код виртуальная машина несовместима со спецификацией JVM. (Вместо, Google инструменты разработки под Android принимают программы на Java как входные и выходные данные. Дальвик байт-код, который является собственным форматом ввода для виртуальной машины на устройствах Android.)

Спектакль

Спецификация JVM дает разработчикам большую свободу действий в отношении деталей реализации. Начиная с Java 1.3, JRE от Oracle содержит JVM под названием HotSpot. Он был разработан как высокопроизводительная JVM.

Для ускорения выполнения кода HotSpot использует своевременную компиляцию. Чтобы ускорить выделение объектов и сборку мусора, HotSpot использует кучу поколений.

Куча поколений

В Куча виртуальной машины Java это область памяти, используемая JVM для распределение динамической памяти.[24]

В HotSpot куча делится на поколения:

  • В молодое поколение магазины недолговечные объекты которые создаются и немедленно собран мусор.
  • Объекты, которые сохраняются дольше, перемещаются в старое поколение (также называемый постоянное поколение). Эта память разделена на (два) пространства Survivors, где хранятся объекты, которые пережили первую и следующую сборку мусора.

В постоянное поколение (или же пермген) использовался для учебный класс определения и связанные метаданные до Java 8. Постоянная генерация не была частью кучи.[25][26] В постоянное поколение был удален из Java 8.[27]

Первоначально не было постоянного поколения, и объекты и классы хранились вместе в одной области. Но поскольку выгрузка классов происходит гораздо реже, чем собираются объекты, перемещение структур классов в определенную область позволило значительно улучшить производительность.[25]

Безопасность

Oracle JRE установлен на большом количестве компьютеров. Таким образом, конечные пользователи с устаревшей версией JRE уязвимы для многих известных атак. Это привело к широко распространенному мнению, что Java по своей сути небезопасна.[28] Начиная с Java 1.7, Oracle JRE для Windows включает функцию автоматического обновления.

До прекращения поддержки подключаемого модуля Java-браузера на любой веб-странице потенциально мог быть запущен Java-апплет, который предоставлял легко доступный поверхность атаки на вредоносные веб-сайты. В 2013 году «Лаборатория Касперского» сообщила, что компьютерные злоумышленники предпочитают плагин Java. Эксплойты Java включены во многие пакеты эксплойтов, которые хакеры размещают на взломанных веб-сайтах.[29] Аплеты Java были удалены в Java 11, выпущенном 25 сентября 2018 г.

Смотрите также

Рекомендации

  1. ^ "jdk-updates / jdk14u: теги". Корпорация Oracle. Получено 2020-03-18.
  2. ^ Билл Веннерс, Внутри виртуальной машины Java Глава 5
  3. ^ "Программа Java Community Process (SM) - JSR: запросы спецификации Java - подробный JSR № 924". Jcp.org. Получено 2015-06-26.
  4. ^ "Программа Java Community Process (SM) - JSR: запросы спецификации Java - деталь JSR № 202". Jcp.org. Получено 2015-06-26.
  5. ^ Спецификация виртуальной машины Javaпервый и второй выпуски также доступны в Интернете).
  6. ^ «Спецификация виртуальной машины Java: Java SE 7 Edition» (PDF). Docs.oracle.com. Получено 2015-06-26.
  7. ^ «Часто задаваемые вопросы - совместимость с Java». scala-lang.org. Получено 2015-11-18.
  8. ^ «Программа Java Community Process (SM) - JSR: запросы спецификации Java - деталь JSR № 292». Jcp.org. Получено 2015-06-26.
  9. ^ «Проект машины да Винчи». Openjdk.java.net. Получено 2015-06-26.
  10. ^ «Новая функция JDK 7: поддержка динамически типизированных языков в виртуальной машине Java». Oracle.com. Получено 2015-06-26.
  11. ^ «Процесс проверки». Спецификация виртуальной машины Java. Sun Microsystems. 1999 г.. Получено 2009-05-31.
  12. ^ Freund, Stephen N .; Митчелл, Джон С. (1999). «Формальная основа для языка байт-кода и верификатора Java». Материалы 14-й конференции ACM SIGPLAN по объектно-ориентированному программированию, системам, языкам и приложениям - OOPSLA '99. С. 147–166. CiteSeerX  10.1.1.2.4663. Дои:10.1145/320384.320397. ISBN  978-1581132380.
  13. ^ http://www-sop.inria.fr/everest/Lilian.Burdy/CBR02dsn.pdf
  14. ^ Дэвид Дж. Эк, Введение в программирование с использованием Java, Седьмое издание, версия 7.0, август 2014 г., раздел 1.3 «Виртуальная машина Java»
  15. ^ Oracle JRockit Введение В архиве 2015-09-06 на Wayback Machine Выпуск R28 на 2. «Понимание своевременной компиляции и оптимизации»
  16. ^ «Oracle осуждает плагин для браузера Java и готовится к его прекращению». Ars Technica. 28 января 2016 г.. Получено 15 апреля 2016.
  17. ^ «Исторические ежегодные тенденции использования языков программирования на стороне клиента, июнь 2015 г.». W3techs.com. Получено 2015-06-26.
  18. ^ Криль, Пол (13 мая 2016 г.). «JavaPoly.js импортирует существующий код Java и вызывает его непосредственно из JavaScript». InfoWorld. Получено 18 июля 2016.
  19. ^ "Домашняя страница проекта TeaVM". Teavm.org. Получено 2015-06-26.
  20. ^ "Dragome Web SDK". Dragome.com. Получено 2015-06-26.
  21. ^ "Bck2Brwsr - APIDesign". Wiki.apidesign.org. Получено 2015-06-26.
  22. ^ Вольфганг Кюн (декатур). j2js-компилятор GitHub
  23. ^ «Список языков, компилируемых в JS · jashkenas / coffeescript Wiki · GitHub». Github.com. 2015-06-19. Получено 2015-06-26.
  24. ^ «Часто задаваемые вопросы о сборке мусора в виртуальной машине Java Hotspot». Sun Microsystems. 6 февраля 2003 г.. Получено 7 февраля 2009.
  25. ^ а б Масамицу, Джон (28 ноября 2006 г.). «Представляя постоянное поколение». Получено 7 февраля 2009.
  26. ^ Наттер, Чарльз (11 сентября 2008 г.). "Первый вкус InvokeDynamic". Получено 7 февраля 2009.
  27. ^ «JEP 122: Удалить постоянное поколение». Корпорация Oracle. 2012-12-04. Получено 2014-03-23.
  28. ^ «Что такое Java, небезопасно ли оно и стоит ли его использовать?». Lifehacker.com. 2013-01-14. Получено 2015-06-26.
  29. ^ «Есть ли защита от эксплойтов Java? | Лаборатория Касперского». Kaspersky.com. 2013-09-09. Архивировано из оригинал на 2015-04-04. Получено 2015-06-26.

внешняя ссылка