Как работает Java:
- Java компилирует код и преобразует его в байтовый код (.class)
- JVM интерпретирует байтовые коды и преобразует их в коды машинного уровня, чтобы его можно было запускать на любом компьютере.
Байт-код в машинный код:
- Байт-код преобразуется в код машинного уровня с использованием словаря инструкций (байтовый в m / c), поскольку разные типы машин (например, Ubuntu, mac, windows и т. Д.) Имеют разные типы набора инструкций.
- Переводчик очень быстро запускает и загружает приложение.
- Одна из проблем заключается в том, что интерпретатор не выполняет никаких оптимизаций, потому что один и тот же байтовый код каждый раз преобразуется в машинный код.
- Для решения этой проблемы используется компилятор C1, который использует кеш кода.
Компилятор C1:
- Поэтому, когда интерпретатор интерпретирует байтовый код, он использует счетчик того, сколько раз один и тот же байтовый код преобразуется в машинный код, который сохраняется в кеше кода.
- Когда счетчик достигает порогового значения, компилятор C1 компилирует коды и сохраняет их в кеше кода, чтобы при выполнении тех же байт-кодов они были получены из кеша кода.
- Кэш кода - это область памяти, отдельная от кучи JVM, которая содержит весь байт-код JVM для метода, скомпилированного в собственный код, каждый из которых называется nmethod1. Здесь хранятся JIT-скомпилированные методы.
- Это также называется JIT (точно вовремя) компиляцией.
- Размер кэша кода по умолчанию составляет 240 МБ в java 8, но мы можем установить другое значение, используя флаг -XReservedCodeCacheSize.
- Порог компиляции по умолчанию - 1500 для компилятора C1.
Компилятор C2:
- Через некоторое время, когда JVM работает в течение некоторого времени, она начинает в фоновом режиме собирать статистику о том, как выполняется код, что называется профилированием кода. Он создает графы потока управления (пути кода). Он пытается найти самые горячие пути кода, как только у него будет достаточно статистики, после чего JVM попросила компилятор C2 выполнить оптимизацию на самых горячих путях кода.
- Он также хранит оптимизированный код в кэше кода.
Оптимизация, выполняемая C2:
- Мертвый код
- Анализ побега
- Петли
- Встраивание методов
- Нулевой контроль Устранение
и т.д. используются компилятором C2 для оптимизации самого горячего кода
Подробнее о C1 и C2:
- Два компилятора, C1 и C2, работают параллельно и продолжают оптимизацию кода.
- . C1 предпочтительнее для клиентского приложения, а C2 предпочтительнее для длительно работающих серверных приложений.
- Многоуровневая компиляция сочетает в себе лучшие возможности обоих компиляторов. Компиляция на стороне клиента обеспечивает быстрое время запуска и быструю оптимизацию, в то время как компиляция на стороне сервера обеспечивает более продвинутую оптимизацию на более поздних этапах цикла выполнения.
- Когда кэш кода ограничен (его использование приближается к ReservedCodeCacheSize или достигает его), для компиляции большего количества методов JIT сначала должен выбросить некоторые уже скомпилированные методы. Отказ от скомпилированных методов известен как очистка кэша кода.
- В JAVA 7 у нас есть возможность выбрать оба компилятора.
- В JAVA 8 оба доступны по умолчанию.
Опережая время, компиляция:
При профилировании вручную или вручную проверяйте поток или дамп памяти из JVM, нам может потребоваться выполнить компиляцию заранее. эта функция включена после JAVA9.
После Java9 у нас есть возможность преобразовать некоторые классы или библиотеки в скомпилированный код перед запуском приложения.
Скомпилируйте класс до:
Прежде чем мы сможем использовать компилятор AOT, нам нужно скомпилировать класс с помощью компилятора Java:
javac <classname>.java
Передайте класс компилятору AOT:
Затем мы передаем получившийся ‹classname› .java компилятору AOT, который находится в том же каталоге, что и стандартный компилятор Java.
jaotc --output
<classname>.so
<classname>.class
Запуск программы
Затем мы можем выполнить программу во время работы программы, которая нам нужна, чтобы использовать флаг -XX: AOTLibrary, чтобы сообщить JVM для скомпилированного класса AOT.
java -XX:AOTLibrary=./
<classname>.so
<classname>
- Мы также можем увидеть, что библиотека была загружена, добавив -XX: + PrintAOT в качестве аргумента JVM.
Вот и все.
Удачного обучения.