2014-09-28 6 views
1

По этой теме: Reasons of getting a java.lang.VerifyErrorПочему java.lang.VerifyError предотвращает успешную компиляцию?

java.lang.VerifyError получает, если версия исполнения JVM новее JVM, которая использовалась для компиляции.

Мы можем исправить эту проблему, используя следующую опцию jvm: -XX:-UseSplitVerifier.

По этим:

https://stackoverflow.com/a/16467026/2674303

использовать этот параметр является 'абсолютно безопасно'.

Таким образом, я не понимаю, почему java.lang.VerifyError является проблемой, которая предотвращает успешную компиляцию. Просьба уточнить. Может быть, это небезопасно для библиотек, которые используют инструмент bytecode?

+2

Это не «предотвращает» успешную компиляцию. Скорее, компиляция была как-то неудачной/ошибочной, вызвав VerifyError. По сути, файл .class оказывается поврежденным. –

+0

(Но упомянутый поток говорит об использовании опции, которая заставляет JVM использовать старый верификатор, а не «улучшенный». Неясно, находится ли обход проблемы в файле класса (в конструкции StackMapTable) или в новый верификатор (используя эту таблицу), но в любом случае обход должен быть абсолютно безопасным.) –

ответ

5

A Q & A, ссылки на которые вы ссылаетесь, чтобы ссылаться на определенную ошибку проверки, что безопасно работать с помощью альтернативного верификатора. Однако есть и другие ошибки проверки, которые вы не должны игнорировать ... и что вы не можете справиться с этим.

Короче говоря, совет в связанном вопросе вообще не применяется. В целом:

  • Переключение на альтернативный вариант, вероятно, не поможет.

  • Если вы полностью отключили верификатор, вы рискуете запуском кода, который может нарушить ограничения типа JVM-безопасности (и т. Д.). Это может привести к проблемам безопасности и/или повреждению кучи и жестким сбоям JVM.


Если у вас есть конкретные VerifyError, что вам нужен совет, пожалуйста, включают полное сообщение об исключении и StackTrace, и описать ситуацию, в которой оно происходит. Обратите внимание, что ответ Андрея верен, что общей причиной ошибок проверки являются ошибки в коде, который выполняет «технологию байт-кода» для различных целей. Часто исправление заключается в изменении другой версии соответствующей зависимости.

+0

И, в идеале, опубликуйте также оскорбительный класс. – Antimony

+0

Таким образом, этот вариант не так безопасен. Даже если вы используете его в соответствующей ситуации, он может скрыть будущие ошибки. – gstackoverflow

+1

Возможно, стоит отметить, что опция '-XX: -UseSplitVerifier' больше не поддерживается в Java 8 и будет полностью проигнорирована. Так что ничего не может исправить. – Holger

1

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

0

Возможно, вы используете Java 7u65 или 8u11? Если да, то эта статья может иметь отношение к вашей проблеме: http://www.takipiblog.com/oracles-latest-java-8-update-broke-your-tools-how-did-it-happen/

Если вы были в ногу с новостями в мире Java в последнее время, вы, наверное, слышали, что последняя Java 8 сборки выпущена Oracle, Java 8u11 (и Java 7u65), представил ошибки и сломал некоторые популярные инструменты, такие как ZeroTurnaround JRebel, Javassist, Google Guice и даже сам Groovy.

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

1

Цель состоит в том, чтобы заставить инструменты и библиотеки генерировать правильный StackMapTable атрибут всякий раз, когда они манипулируют Java байткод, так что JVM не нужно делать медленно и сложный type inferencing этап проверки, а только сделать быстрый и простой type checking фазы.

-XX:-UseSplitVerifier устарел на Java 8, это больше не поможет.

+0

'-XX: -UseSplitVerifier' не был устарел на Java 8, он был полностью удален. – Holger

1

VerifyError бросается во время загрузки класса JVM, поэтому он отображается на уровне времени выполнения, а не на уровне компиляции.

  1. Не всегда мы можем исправить probem, используя старый верификатор. Есть конкретный случай, когда это помогает. Это помогает только тогда, когда класс является старшим для более старого верификатора и отсутствует StackMapTable, который был введен в JVM 1.6 и обязателен в JVM 1.7

  2. Если вы хотите избавиться с точки зрения JVM. Вы все равно можете отключить целую проверку, но это может вызвать проблемы.

  3. Управление байткодом всегда опасно, когда вы не знаете, что делаете вы. Теперь основные библиотеки манипулирования байт-кодами поддерживают вычисления StackMapFrames, чтобы они могли генерировать байт-код, который является пророком для каждой виртуальной машины. Но все же пользователь может генерировать байт-код, который неверен на уровне файла класса, в этом случае JVM все равно будет загружать VerifyError при загрузке, SplitVerifier не поможет. Только отключение проверки заставляет VM загружать этот класс, но может быть некоторая ошибка, когда он будет выполняться.

Смежные вопросы