Что такое AOT компиляция и с чем её едят?

Одним из новшеств Java 9 является Ahead-Of-Time (AOT) компиляция. Поэтому в данной статье я решил немного рассказать об основных аспектах того, что же это такое.

java9

AOT компиляция – это статическая компиляция и те, кто работал с языком C хорошо знакомы с ней. Суть заключается в том, что на этапе компиляции наш исходный код превращается в исполняемый код. По итогу мы получаем исполняемый файл, который мы можем запустить в любой момент. Соответственно, до начала работы программы нам требуется больше времени. Поэтому данный вид компиляции так и называется Ahead-Of-Time.

На данный в Java мы привыкли иметь дело с Just-In-Time (JIT) компиляцией, которая происходит во время работы нашего приложения.

Но, не стоит думать, что в Java 9 мы полностью отказываемся от JIT компиляции в пользу AOT. Нет, в Java 9 планируется ДОБАВИТЬ возможность AOT.

Использовать её мы сможем с помощью jaotc. Данная утилита будет гарантированно работать для модуля java.base, который работает объектами, структурами данных и потоками. Следовательно, мы можем сказать, что AOT компиляция не является полноценным модулем Java 9, а находится на стадии внедрения.

После того, как мы рассмотрели, что же такое AOT компиляция возникает вопрос:

А для чего мне необходима AOT компиляция?

Данный вид компиляции имеет следующие основные преимущества:

  • Время запуска приложения
    Для холодного старта (первого запуска нашей программы) нам необходимо значительно большее время по сравнению с JIT компиляцией. Но, после того, как код статически скомпилирован, время старта не отличается от времени старта такой же программы на языке C.
  • Невозможность декомпиляции
    Исполняемый код, который мы получаем в результате AOT компиляции можно дизассемблировать со значительными сложностями, а декомпилировать байт код в Java код не составляет трудности.

Может возникнуть ложное мнение, что Java станет работать со скоростью языка C, но это не так.

c_language

В языке С высокая скорость работы достигается за счёт “предоставления свободы” разработчику за счёт безопасности поведения.

Например, если в массиве 100 элементов, а мы хотим получить доступ к 101 элементу и т.д, то в языке Java мы получим ArrayOutOfBoundsException, в то время, как в С, в лучшем случае, мы получим segfault. Т.е. Java проверяет, чтобы мы не нанесли вреда. За подобные проверки в Java мы и расплачиваемся скоростью.

Но, не стоит думать, что С работает быстрее Java во всех случаях, это не так.

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

Данная оптимизация, временами, становится крайне “дорогой”, потому что дополнительные данные, возникающие во время выполнения этой оптимизации может “не помещаться” в оперативной памяти и временно, необходимо записывать её на диск. Это “непозволительная роскошь” для JIT компилятора.

Заключение

Не существует однозначного ответа на вопрос “Какой вид компиляции лучше?”. Ответ крайне зависит от самого приложения и целей его использования. AOT компиляция крайне хорошо подходит для встраиваемых систем, так как они не имеют высоких вычислительных мощностей. Если “железо слабое”, то и динамическая компиляция становится крайне слабым инструментом.

java_ee

С другой стороны, для корпоративных систем динамическая (JIT) компиляция, вероятнее всего, останется более приоритетной.