Насколько безопасно использовать -XX:-UseSplitVerifier?

Известны проблемы совместимости с скомпилированным кодом JDK7 с использованием инструментария. Что касается http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

Файлы классов с номером версии 51 проверяются исключительно с помощью верификатора проверки типов, и, таким образом, методы должны иметь атрибуты StackMapTable, когда это необходимо. Для файлов классов с версией 50 JVM Hotspot будет (и продолжает) переключаться на верификатор с выводом типа, если в стеке карты отсутствуют или неверны. Это аварийное переключение не происходит для файлов классов с версией 51 (версия по умолчанию для Java SE 7). Любой инструмент, который изменяет байт-код в файле класса версии 51, должен обязательно обновлять информацию стековой карты, чтобы она соответствовала байт-коду, чтобы пройти проверку.

Решение заключается в использовании -XX:-UseSplitVerifier вкратце здесь: https://community.oracle.com/blogs/fabriziogiudici/2012/05/07/understanding-subtle-new-behaviours-jdk-7

Насколько это безопасно? Я полагаю, что Oracle поставил эту проверку по причине. Если я не использую это, я могу рискнуть некоторыми другими проблемами.

Какие могут быть последствия использования -XX:-UseSplitVerifier?

Спасибо,

Петр.

3 ответа

Короче говоря, это совершенно безопасно.

Начиная с Java 6, компилятор Oracle создает файлы классов с помощью StackMapTable. Основная идея заключается в том, что компилятор может явно указать тип объекта вместо того, чтобы делать это во время выполнения. Это обеспечивает небольшое ускорение во время выполнения в обмен на дополнительное время во время компиляции и некоторую сложность в скомпилированном файле класса (вышеупомянутый StackMapTable).

В качестве экспериментальной функции она не была включена по умолчанию в компиляторе Java 6. По умолчанию среда выполнения проверяет сами типы объектов, если не существует StackMapTable.

До Java 7. Oracle делала это обязательным: компилятор генерирует их, а среда выполнения проверяет их. Он по-прежнему использует старый верификатор, если StackMapTable отсутствует... но только для файлов классов из Java 6 или более ранней версии (версия 50). Файлы классов Java 7 (версия 51) необходимы для использования StackMapTable, и поэтому среда выполнения не уменьшит их.

Это проблема, только если ваши файлы классов были сгенерированы без StackMapTable. Например, если вы использовали не Oracle JVM. Или, если вы позже перепутали с байт-кодом - например, оснастили его для использования с отладчиком, оптимизатором или анализатором покрытия кода.

Но вы можете обойти это! Oracle JVM предоставляет параметр -XX:+UseSplitVerifier для принудительного возврата среды выполнения к верификатору старого типа. Это не волнует StackMapTable.

На практике желаемая оптимизация скорости и эффективности во время выполнения не материализовалась: если она существует, то этого недостаточно для того, чтобы кто-то заметил. Поскольку новый верификатор типов не предоставляет никаких новых функций (только оптимизация), отключить его абсолютно безопасно.

Объяснение Oracle можно найти по адресу http://www.oracle.com/technetwork/java/javase/compatibility-417013.html если вы ищете JSR 202.

Да - это безопасно Как говорит Юдеберт, это просто немного замедляет загрузку классов.

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

Вот ключ: у компилятора уже есть вся информация, которую генерирует первый проход - таким образом (в Java 6 и 7) он сохраняет ее в таблице StackMap в файле класса.

Это ускоряет загрузку классов, потому что загрузчик классов не должен делать этот первый проход. Вот почему он называется Split Verifier, потому что работа разделена между компилятором и механизмом загрузки во время выполнения. Когда вы используете опцию -XX:-UseSplitVerifier, вы указываете Java делать обе передачи во время загрузки класса (и игнорировать любую таблицу StackMap). Многие продукты (например, профилировщики, которые изменяют байт-код во время загрузки) изначально не знали о таблице StackMap, поэтому, когда они изменяли классы во время загрузки, таблица StackMap из компилятора устарела и вызвала ошибки.

Итак, подведем итог: опция -XX:-UseSplitVerifier замедляет загрузку классов. Это не влияет на безопасность, производительность и функциональность во время выполнения.

Фреймы стековой карты были добавлены в Java 7, и "prashant" утверждает, что идея ошибочна, и предлагает разработчикам всегда использовать -XX:-UseSplitVerifier флаг, чтобы избежать их использования.

Подробнее: Проверка байт-кода Java 7: огромный шаг назад для JVM

Другие вопросы по тегам