Разное

Jit java: Java HotSpot JIT компилятор — устройство, мониторинг и настройка (часть 1) / Хабр

Содержание

В Java 9 появится Ahead-Of-Time компиляция. Это как? — новости на Tproger

Недавно стало окончательно известно — в Java 9 будет AOT-компиляция. Мы решили рассказать о том, как это будет, зачем это нужно, а также развеять несколько устойчивых мифов, которые сложились вокруг статической и динамической компиляции.

Какая-какая компиляция?

Статическая, или Ahead-Of-Time (AOT) компиляция — это самая обычная компиляция, которую мы привыкли видеть в языке Си. Исходный код превращается в исполняемый, и на выходе получается исполняемый файл, который можно запустить позже. На статическую компиляцию требуется дополнительное время до начала работы программы, отсюда и название. Существует ещё динамическая, или Just-In-Time (JIT) компиляция — она осуществляется прямо во время работы программы, «на лету». Именно она и используется в Java в настоящий момент.

А в Java 9 хотят заменить её на статическую?

Нет. В Java 9 планируют добавить возможность AOT-компилятор в качестве альтернативы (но не замены) существующим инструментам. Утилита будет называться jaotc. В Java 9 она гарантированно будет работать только для модуля java.base, который содержит всё необходимое для работы с объектами, потоками и структурами данных — то, без чего не может обойтись ни одно приложение. Исходя из этого, AOT-компиляцию в Java 9 всё ещё можно назвать лишь экспериментальной возможностью.

А зачем это нужно?

AOT-компиляция имеет несколько специфических преимуществ. Во-первых, это защита от декомпиляции. Байткод Java можно без особого труда декомпилировать в код на Java, и, таким образом, взломать программу (которая, например, требует лицензионный ключ). Исполняемый код же можно лишь дизассемблировать, и, думается, любой может сравнить сложность поиска каких-то деталей в коде на Java и ассемблерном коде. Обфускация же далеко не панацея, т.к. она трудно реализуема при активном использовании рефлексии и всё равно не даёт стопроцентной защиты. Во-вторых, стоит обратить внимание на время запуска приложения. Для первого запуска (так называемого «холодного старта») приложению требуется значительное количество времени. Для скомпилированного статически кода на Java стартовое время не отличается от старта аналогичной программы на Си:

То есть, получается, со статической компиляцией мы получим в Java скорость Си?

Нет. Си достигает значительной скорости за счёт многих допущений небезопасного поведения. Например, в случае выхода за границы массива в Си случится segfault (в лучшем случае), а в Java просто вылетит ArrayOutOfBoundsException. Подобные проверки не бесплатны, за них приходится платить производительностью как в случае динамической компиляции, так и в случае статической.

Неверным также является представление, что Си в целом работает быстрее Java. Так, в Java компилятору доступен весь код всех подключенных библиотек, а значит, он может оптимизировать их работу наиболее выгодным для данного приложения путём. В Си же библиотеки могут подключаться в виде машинного кода, и никакие дополнительные оптимизации для них недоступны.

Так значит, JIT для Java подходит лучше? Это ведь всё-таки динамический язык.

Такое утверждение тоже будет неверным. Оптимизации, которые производит компилятор, могут быть достаточно сложными и ресурсоёмкими, могут требовать итеративного пересчёта и анализа всей программы целиком. Зачастую в процессе оптимизации возникает такое количество дополнительных данных, что хранить их в оперативной памяти невозможно, и требуется их промежуточная запись на диск. Всего этого JIT-компилятор просто не может себе позволить. Очень заметна разница в производительности между JIT-исполняемым кодом и AOT-компилированным, например, при работе с элементами пользовательского интерфейса.

Что-то я совсем запутался. Так что же лучше?

На этот вопрос нельзя дать однозначного ответа. Для разных приложений и для разных целей выбор может быть разным. Главное, что теперь он будет. Конечно, AOT-компиляторы Java существовали и раньше, однако мало кто из них может похвастаться полноценной поддержкой свежих спецификаций Java. Теперь, когда за дело взялись специалисты из Oracle, возможно, ситуация изменится в лучшую сторону. Про AOT-компиляцию Java кода есть отличный доклад Никиты Липского, на который мы в основном и опирались при подготовке данной статьи:

Можно привести пример, в каких ситуациях статическая компиляция будет явно лучше, чем JIT?

При разработке для встраиваемых систем и мобильных платформ, скорее всего, AOT-компиляция будет лучшим выбором. Встраиваемые системы чаще всего не обладают теми же вычислительными мощностями, что и настольные компьютеры или сервера, а чем слабее железо, тем дороже динамическая компиляция. В случае с мобильными устройствами решающую роль играет другой фактор — нагрузка на аккумулятор. Динамическая компиляция требует много большего расхода энергии, чем выполнение уже скомпилированного кода. Так, для iOS политика распространения приложений вовсе запрещает любую динамическую загрузку кода, поэтому Java фактически невозможно использовать для программирования под устройства Apple.

А можно больше подробностей про то, что именно мы увидим в Java 9?

Мы увидим утилиту jaotc, которая сможет создавать нативные исполняемые файлы для Linux x64, основанные на модуле java.base.

Выглядеть это будет примерно следующим образом. Мы можем создать ELF-файл:

jaotc --output libHelloWorld.so HelloWorld.class

Затем подключить его в качестве библиотеки для исполнения другого кода:

java -XX:AOTLibrary=./libHelloWorld.so HelloWorld

Причём (по крайней мере, в этом релизе) для AOT-компиляции и для запуска должны использоваться одни и те же параметры:

jaotc -J-XX:+UseParallelGC -J-XX:-UseCompressedOops --output libHelloWorld.so HelloWorld.class 
java -XX:+UseParallelGC -XX:-UseCompressedOops -XX:AOTLibrary=./libHelloWorld.so HelloWorld

Больше технических деталей можно узнать на сайте OpenJDK.

В статье использовано изображение из Takipi Blog

Оптимизации генерации кода в JIT-компиляторе виртуальной машины Java

Похожие презентации:

Генерация и оптимизация кода

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

Как выбрать язык программирования?

Введение в Java. (Урок 1)

Java-технологии

Высокопроизводительные вычисления

Программирование на Java. Введение

Распараллеливание на компьютерах с общей памятью

Код. Компилятор

Программирование на языке Java. Введение. (Лекция 1)

1. Дипломная работа «Оптимизации генерации кода в JIT-компиляторе виртуальной машины Java» 

Санкт-Петербургский государственный университет
Математико-механический факультет
Кафедра системного программирования
Дипломная работа
«Оптимизации генерации кода в JITкомпиляторе виртуальной машины
Java»
Научный руководитель
Куксенко С.В.
Рецензент
Салищев С.И.
Выполнил
Проничкин Дмитрий 544гр.
2008

2. Актуальность работы

• Постоянное совершенствование микроархитектуры
процессоров
• Особенности новой микроархитектуры Intel Core
• Увеличение важности производительности front-end процессора
• Работа front-end влияет не только на производительность, но и
на флуктуацию при ее измерении
• Отсутствие работ, учитывающих данные особенности
микроархитектуры Core, даже в Intel Compiler

3.

Результаты
Разработаны идеи и эвристики для оптимизации линеаризации и
выравнивания кода
Опробована схема удаления ветвлений в коде
В генераторе кода JIT-компилятора виртуальной машины Apache
Harmony реализованы улучшения линеаризации и выравнивания
кода, удаления ветвлений
Получен прирост производительности на микротестах и популярных
бенчмарках, таких как SciMark (Monte Carlo – прирост 60%)
Увеличена стабильность метрик производительности
Изменения приняты и интегрированы в Apache Harmony

4. Apache Harmony

• Открытая реализация виртуальной машины
Java
• JIT-компилятор Jitrino.OPT – оптимизирующий
компилятор с возможностью профилировки и
перекомпиляции
• Особенности front-end микроархитектуры
Core не учтены

5. Выравнивание кода

• Отсутствие trace cache по сравнению с
микроархитектурой NetBurst
• Линия выборки (fetch line) 16 байт
• Особенности предсказателя переходов
• Дополнительная возможность процессора – loop
stream detector
• Все эти особенности учтены и разработана эвристика
для выравнивания кода

6.

Линеаризация кода• Расположение базовых блоков графа потока управления в
линейном порядке
• Алгоритм “bottom-up”, имеющий много свойств, положительных для
front-end процессора
• Найдены
возможности для
улучшения под
микроархитектуру
Core
• Разработана
эвристика для
оптимизации
алгоритма

7. Удаление ветвлений

• Все современные микроархитектуры – конвейерные
суперскалярные
• Неправильно предсказанный условный переход
приводит к задержке работы конвейера
• Иногда можно удалить ветвление, заменив его на
более сложные, но линейные вычисления
• Схема удаления ветвлений опробована на бенчмарке
SciMark, получен значительный прирост
производительности

English     Русский Правила

JIT в Java | Java JIT

следующий → ← предыдущая

Когда мы пишем программу на любом языке программирования, она требует преобразования этого кода в машинопонятную форму, потому что машина понимает только двоичный язык.

В зависимости от языков программирования компилятор различается. Компилятор — это программа, которая преобразует язык высокого уровня в код машинного уровня. Язык программирования Java использует компилятор с именем javac . Он преобразует код языка высокого уровня в машинный код (байт-код). JIT — это часть JVM, оптимизирующая производительность приложения. JIT означает Java-In-Time Compiler . JIT-компиляция также известна как динамическая компиляция. В этом разделе мы узнаем , что такое JIT в Java, его работу, и фазы JIT-компилятора .

Что такое JIT в Java?

JIT на Java является неотъемлемой частью

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

JIT-компиляция включает два подхода AOT (компиляция с опережением времени) и интерпретация для перевода кода в машинный код. Компилятор AOT компилирует код в собственный машинный язык (такой же, как обычный компилятор). Он преобразует байт-код виртуальной машины в машинный код. Компиляторы JIT выполняют следующие оптимизации:

  • Метод Встраивание
  • Локальные оптимизации
  • Оптимизация потока управления
  • Постоянное складывание
  • Удаление мертвого кода
  • Глобальные оптимизации
  • Эвристика для оптимизации сайтов звонков

Преимущества JIT-компилятора

  • Требуется меньше памяти.
  • Оптимизация кода выполняется во время выполнения.
  • Используются различные уровни оптимизации.
  • Уменьшает число ошибок страниц.

Недостатки JIT-компилятора

  • Увеличивает сложность программы.
  • Программа с меньшим количеством строк кода не использует JIT-компиляцию.
  • Использует много кэш-памяти.

Работа компилятора JIT

Если переменная среды JIT-компилятора установлена ​​правильно, JVM считывает файл .class (байт-код) для интерпретации, после чего передает JIT-компилятору для дальнейшей обработки. Получив байт-код, JIT-компилятор преобразует его в собственный код (машиночитаемый код).

  • Java Development Kit (JDK) предоставляет компилятор Java (javac) для компиляции исходного кода Java в байт-код (файл .class). После этого JVM загружает файл .class во время выполнения и преобразует байт-код в двоичный код (машинный код). Далее машинный код используется интерпретатором.
  • Мы знаем, что интерпретация байт-кода Java снижает производительность собственного приложения. Это причина для реализации JIT-компилятора. Компилятор JIT повышает производительность приложения, компилируя байт-код в собственный машинный код.
  • Он включен по умолчанию при вызове метода. JVM напрямую вызывает скомпилированный код метода без его интерпретации. Это не требует большого использования памяти.

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

На следующем рисунке показана функциональная взаимосвязь JIT-компилятора с JRE и JVM.

Уровни оптимизации

Он также известен как уровень оптимизации

. Каждый уровень обеспечивает определенный уровень производительности. Компилятор JIT обеспечивает следующий уровень оптимизации:

  • Холодный: Используется при запуске большого Java-приложения. Цель состоит в том, чтобы достичь наилучшей скорости скомпилированного кода.
  • Теплый: После запуска Java-приложения большинство методов скомпилировано, когда они достигают порога вызова.
  • Горячее: Методы, потребляющие более 1% , запланированы для горячей компиляции.
  • Very Hot: Метод запланирован на очень жарко, если они не палящие, а горячие.
  • Scorching: Методы, которые потребляют более 5% , запланированы для компиляции scorching.

Уровни оптимизации по умолчанию и начальный уровень теплый . Мы получаем лучшую производительность, если уровень оптимизации выше, но это увеличивает стоимость памяти и процессора.

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

  • Анализ побега
  • Устранение частичного резервирования

Приведенные выше методы используют больше памяти и ЦП для повышения производительности приложения Java. Это увеличивает стоимость компиляции, но компенсирует производительность.


Следующая темаКак очистить экран в Java

← предыдущая следующий →


Для видео Присоединяйтесь к нашему каналу Youtube: Присоединяйтесь сейчас


Обратная связь

  • Отправьте свой отзыв на [email protected]

Помогите другим, пожалуйста, поделитесь


Изучите последние учебные пособия


Подготовка


Современные технологии


Б.

Тех / МСА

Компилятор Just In Time — GeeksforGeeks

Улучшить статью

Сохранить статью

Нравится Статья

Шреяш Шарма 3

автор

1 опубликованная статья

  • Читать
  • Обсудить
  • Улучшить статью

    Сохранить статью

    Нравится Статья

    JIT-компилятор или JIT-компилятор является важной частью JRE (Java Runtime Environment), которая отвечает за оптимизацию производительности Java-приложений во время выполнения. Компилятор является одним из ключевых аспектов при определении производительности приложения для обеих сторон, то есть для конечного пользователя и разработчика приложения. Давайте более подробно рассмотрим компилятор Just In Time на Java.

    Байт-код — одна из наиболее важных функций Java, которая помогает в кросс-платформенном выполнении. Способ преобразования байт-кода в собственный машинный язык для выполнения оказывает огромное влияние на его скорость. Эти байт-коды должны быть интерпретированы или скомпилированы в соответствующие машинные инструкции в зависимости от архитектуры набора инструкций.

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

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

    Работа с JIT-компилятором

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

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

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *