Почему JVM-кеш JIT-скомпилированный код?

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

Вопрос в том, почему этот скомпилированный код не кэшируется на диск для использования при последующем использовании той же функции/класса?

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

Ответ 1

Не прибегая к cut'n'paste ссылки, которую отправил @MYYN, я подозреваю, что это связано с тем, что оптимизация, выполняемая JVM, не является статической, а скорее динамической, основанной на шаблонах данных, а также на шаблонах кода. Вероятно, эти шаблоны данных будут меняться в течение срока службы приложения, делая оптимизацию кэширования менее оптимальной.

Таким образом, вам понадобится механизм для определения того, были ли оптимальные оптимизированы сохраненные оптимизации, после чего вы могли бы просто повторно оптимизировать "на лету".

Ответ 2

Oracle JVM действительно документирован для этого - цитирование Oracle,

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

Я не знаю, почему все сложные реализации VM не предлагают аналогичные варианты.

Ответ 3

Обновлено до существующих ответов - Java 8 имеет JEP, предназначенный для решения этой проблемы:

= > JEP 145: Скомпилированный код кэша. Новая ссылка.

На очень высоком уровне его заявленная цель :

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

Надеюсь, это поможет.

Ответ 4

Excelsior JET имеет кеширующий JIT-компилятор с версии 2.0, выпущенный еще в 2001 году. Более того, его компилятор AOT может перекомпилировать кеш в один DLL/общий объект, используя все оптимизации.

Ответ 5

Я не знаю реальных причин, которые никак не связаны с реализацией JVM, но я могу думать о некоторых правдоподобных:

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

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

Мой предпочтительный способ состоял бы в том, чтобы иметь отдельный переводчик bytecode-to-native, который вы могли бы использовать, чтобы сделать что-то вроде этого явно заранее, создавая файлы классов, которые явно созданы для конкретной виртуальной машины, возможно, с исходным байт-кодом в них так что вы можете работать с разными виртуальными машинами. Но это, вероятно, происходит из моего опыта: я в основном делаю Java ME, где действительно больно, что компилятор Java не умнее компиляции.