Рубрики
Без рубрики

Ява Под капотом

Этот пост предлагает краткое введение в то, как Java выполняет код, написанный на языке Java под… Помечен java, jvm, байт-кодом.

Этот пост предлагает краткое введение в то, как Java выполняет код, написанный на языке Java под капотом.

Вот список, который я собираюсь изучить,

1. Компилятор Java 2. JVM

Является ли Java компилируемым языком или интерпретируемым языком?

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

Но в Java компилятор Java не преобразует исходный код Java в машинный код (т.е. двоичный) напрямую. Вместо этого он преобразует исходный код в промежуточный код, называемый байт-код . Затем виртуальная машина Java (JVM) выполнит этот байт-код, интерпретируя его в машинный код. Но JVM использует компилятор Just In Time (JIT) для компиляции части кода в машинный код (машинный код). Таким образом, Java является одновременно компилируемым и интерпретируемым языком.

javac является компонентом набора для разработки Java (JDK), который определяет компилятор Java.

Компилятор Java преобразует исходный код, расположенный в файлах .java , в файлы .class , которые по сути являются байт-кодами этих Java-кодов.

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

Если у вас есть несколько классов в одном файле .java , он сгенерирует файл .class для каждого класса.

После того, как javac компилирует исходный код в байт-код, JVM выполняет его. Это называется фазой запуска программы.

JVM разделена на три основные подсистемы.

  1. Подсистема загрузки классов
  2. Области данных во время выполнения
  3. Механизм выполнения

Помимо этого, он состоит из Библиотек собственных методов , которые являются исполняемым кодом для конкретной платформы (написанным на c/c++), содержащимся в библиотеках или библиотеках DLL, и Java Native Interface (JNI) , который интерфейс, используемый механизмом выполнения для взаимодействия с библиотеками собственных методов.

Подсистема загрузки классов

Подсистема загрузки классов используется для загрузки, связывания и инициализация файлов .class , созданных javac

Погрузка

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

  1. Загрузчик классов начальной загрузки – Этот загрузчик отвечает за загрузку основных классов, таких как java.lang. Объект , java.язык. Класс и java.язык. Загрузчик классов из начальной загрузки путь к классу, который rt.jar . Этот загрузчик классов является родительским для всех загрузчиков классов.

  2. Загрузчик расширений – Этот загрузчик продолжает процесс загрузки, загружая классы, которые являются расширением стандартных основных классов Java. Эти классы доступны для всех приложений, работающих на платформе (т.е. JRE).

  3. Загрузчик приложений – Загрузка заканчивается загрузкой начального пользовательского класса, который находится в пути к классу уровня приложения, который указан в переменной окружения .

Вышеуказанные загрузчики классов будут следовать Алгоритму иерархии делегирования при загрузке класса

Что такое Алгоритм иерархии делегирования?

Когда загрузчику классов запрашивается загрузка класса, загрузчик классов делегирует запрос родительскому загрузчику классов.

Например, если JVM запрашивается для загрузки класса, загрузчик классов приложения делегирует его Загрузчику классов расширения. Затем Загрузчик классов расширения делегирует его загрузчику классов начальной загрузки. Если загрузчику классов начальной загрузки не удается загрузить класс, то загрузчик классов расширения попытается загрузить его. Только в том случае, если загрузчику классов расширения не удастся найти класс, загрузчик классов приложения попытается загрузить класс.

Если класс не найден даже после того, как загрузчик классов приложения попытается его загрузить, то будет выдана ошибка.

Связывающий

Связывание класса включает в себя следующие операции,

  1. Проверка – Убедитесь, что байт-код структурно корректен.

  2. Подготовка – Память будет выделена для статических переменных, и им будут присвоены значения по умолчанию.

  3. Разрешение – Ссылки на символическую память будут заменены фактическими значениями.

Инициализация

Это заключительный этап подсистемы загрузки классов. Здесь всем статическим переменным будут присвоены их исходные значения, а затем будет выполнен статический блок. В результате будет выполнен метод main() , а следовательно, и другие классы. Это приведет к загрузке, связыванию и инициализации этих классов.

Область данных времени выполнения

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

В JVM есть пять основных областей данных.

Область метода

Самый простой тип памяти для управления. Это общий ресурс. На JVM существует только одна область методов. Он может состоять из всего, что может быть полностью определено во время компиляции, например статических переменных, констант (возможно), кода.

Площадь Кучи

Наименее организованная и наиболее динамичная область данных. Это ресурс, который является общим для всех потоков. Куча используется для динамического выделения и освобождения памяти для экземпляров классов (объектов) и массивов. Для выделения хранилища кучи необходимы специальные операции, такие как создать . Память, выделенная для объектов, никогда явно не освобождается, и это пространство освобождается сборщиком мусора (обсуждается позже). Память, выделенная для кучи, не является непрерывной. Освобождение может оставить “дыры” в куче (так называемая фрагментация).

Площадь штабеля

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

  • Массив локальных переменных – хранит локальные переменные и соответствующие им значения.

  • Стек операндов – Если для выполнения требуется какая-либо промежуточная операция, то она будет действовать как рабочее пространство во время выполнения.

  • Данные кадра – Здесь хранятся все символы, соответствующие методу. Здесь также хранится информация о блоке catch .

Регистры ПК

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

Собственные стеки Методов

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

Механизм выполнения

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

Переводчик

Интерпретатор интерпретирует байт-код быстрее, но выполняется медленно. Если один метод вызывается несколько раз, каждый раз интерпретатор будет его интерпретировать.

JIT-компилятор

Компилятор Just In Time (JIT) определит горячие точки кода, которые являются кодом, который повторяется и многократно интерпретируется, и скомпилирует этот код в машинный код (машинный код), что повышает производительность. Компилятор JIT состоит из следующих компонентов.

  • Генератор промежуточного кода – Создает промежуточный код для оптимизации.

  • Оптимизация кода – оптимизируйте промежуточный код, сгенерированный выше. Такие, как устранение общих подвыражений, перевод из операций стека в операции с регистрами, сокращение обращений к памяти за счет выделения регистров и т.д.

  • Генератор целевого кода – Генерация машинного кода (Собственный код)

  • Профилировщик – Находит горячие точки в байт-коде.

Сборщик мусора

Собирает и удаляет объекты, на которые нет ссылок (недоступные объекты/сироты). Сборку мусора также можно запустить вручную, вызвав System.gc() .

Спасибо за чтение.

Увидимся в следующем посте!

Оригинал: “https://dev.to/sivantha96/java-under-the-hood-3071”