Причины получения java.lang.VerifyError

Я расследую следующее java.lang.VerifyError

java.lang.VerifyError: (class: be/post/ehr/wfm/application/serviceorganization/report/DisplayReportServlet, method: getMonthData signature: (IILjava/util/Collection;Ljava/util/Collection;Ljava/util/HashMap;Ljava/util/Collection;Ljava/util/Locale;Lorg/apache/struts/util/MessageRe˜̴Mt̴MÚw€mçw€mp:”MŒŒ
                at java.lang.Class.getDeclaredConstructors0(Native Method)
                at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357)
                at java.lang.Class.getConstructor0(Class.java:2671)

Это происходит при запуске сервера jboss, на котором развернут сервлет. Он скомпилирован с jdk-1.5.0_11, и я попытался перекомпилировать его с jdk-1.5.0_15 безуспешно. То есть компиляция работает нормально, но при развертывании возникает ошибка java.lang.VerifyError.

Когда я изменил имя метода и получил следующую ошибку:

java.lang.VerifyError: (class: be/post/ehr/wfm/application/serviceorganization/report/DisplayReportServlet, method: getMD signature: (IILjava/util/Collection;Lj    ava/util/Collection;Ljava/util/HashMap;Ljava/util/Collection;Ljava/util/Locale;Lorg/apache/struts/util/MessageResources ØÅN|ØÅNÚw€mçw€mX#ÖM|XÔM
            at java.lang.Class.getDeclaredConstructors0(Native Method)
            at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357
            at java.lang.Class.getConstructor0(Class.java:2671)
            at java.lang.Class.newInstance0(Class.java:321)
            at java.lang.Class.newInstance(Class.java:303)

Вы можете видеть, что отображается больше сигнатуры метода.

Фактическая сигнатура метода

  private PgasePdfTable getMonthData(int month, int year, Collection dayTypes,
                          Collection calendarDays,
                          HashMap bcSpecialDays,
                          Collection activityPeriods,
                          Locale locale, MessageResources resources) throws   Exception {

Я уже пытался смотреть на это с javap и это дает подпись метода, как и должно быть.

Когда другие мои коллеги проверяют код, компилируют и разворачивают его, они сталкиваются с той же проблемой. Когда сервер сборки берет код и развертывает его в средах разработки или тестирования (HPUX), возникает та же ошибка. Также автоматическая машина тестирования под управлением Ubuntu показывает ту же ошибку во время запуска сервера.

Остальная часть приложения работает нормально, только один сервлет вышел из строя. Любые идеи, где искать было бы полезно.

23 ответа

Решение

java.lang.VerifyError может быть результатом, если вы скомпилировали против другой библиотеки, чем вы используете во время выполнения.

Например, это случилось со мной при попытке запустить программу, скомпилированную с Xerces 1, но Xerces 2 был найден в пути к классам. Обязательные занятия (в org.apache.* пространства имен) были найдены во время выполнения, поэтому ClassNotFoundException не было результата. В классы и методы были внесены изменения, так что сигнатуры методов, найденные во время выполнения, не совпадали с тем, что было во время компиляции.

Обычно компилятор будет отмечать проблемы, когда сигнатуры методов не совпадают. JVM проверит байт-код еще раз, когда класс загружен, и выдает VerifyError когда байт-код пытается сделать что-то, что не должно быть разрешено - например, вызвать метод, который возвращает String а затем сохраняет это возвращаемое значение в поле, которое содержит List,

java.lang.VerifyError худшие.

Вы получите эту ошибку, если размер байт-кода вашего метода превысит ограничение в 64 КБ; но вы, вероятно, заметили бы это.

Вы на 100% уверены, что этот класс отсутствует в пути к классам в другом месте вашего приложения, может быть, в другой банке?

Кроме того, из вашей трассировки стека, является кодировка символов исходного файла (utf-8?) Это верно?

Как сказал Кевин Панко, это в основном из-за смены библиотеки. Так что в некоторых случаях "чистый" проект (каталог), сопровождаемый сборкой, делает свое дело.

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

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

По сути, VerifyError может возникать только в случае ошибки компилятора или когда файл класса поврежден каким-либо иным способом (например, из-за неисправного ОЗУ или сбоя HD).

Попробуйте скомпилировать с другой версией JDK и на другой машине.

Я исправил эту ошибку на Android, сделав проект, в который импортировал библиотеку, как описано здесь http://developer.android.com/tools/projects/projects-eclipse.html

Раньше я просто ссылался на проект (не делая его библиотекой) и получал этот странный VerifyError.

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

В моем случае мой проект Android зависит от другого проекта Java, скомпилированного для Java 7. java.lang.VerifyError исчез после того, как я изменил Compliance Compliance Level этого Java-проекта на 6.0

Позже я узнал, что это проблема Dalvik: https://groups.google.com/forum/?fromgroups

Я получил эту проблему из-за pack200 искажения файла класса. Немного поиска перевернул эту ошибку Java. В основном, установка --effort=4 вызвал проблему, чтобы уйти.

Используя Java 1.5.0_17 (хотя он появлялся в каждом варианте Java 1.5, я попробовал его).

Это может произойти на Android, когда вы пытаетесь загрузить библиотеку, скомпилированную с использованием Oracle JDK.

Вот проблема для Ning Async HTTP-клиента.

Я исправил аналогичную проблему java.lang.VerifyError, заменив

        catch (MagickException e)

с

        catch (Exception e)

где MagickException был определен в проекте библиотеки (от которого зависит мой проект).

После этого у меня есть java.lang.NoClassDefFoundError о классе из той же библиотеки (исправлено в соответствии с /questions/4897423/javalangnoclassdeffounderror-v-eclipse-no-ne-s-ant/4897435#4897435).

Минимальный пример, который генерирует ошибку

Одна простая возможность - использовать Jasmin или вручную редактировать байт-код с помощью редактора двоичных файлов.

Давайте создадим void метод без return инструкция (генерируется return; заявление на Java), что JVMS говорит, что это незаконно.

В Жасмин мы могли бы написать:

.class public Main
.super java/lang/Object

.method public static main([Ljava/lang/String;)V
   aload_0 ; Just so that we won't get another verify error for empty code.
.end method

Затем мы делаем javac Main.j а также javap -v Main говорит, что мы собрали:

public static void main(java.lang.String[]);
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=1, locals=1, args_size=1
       0: aload_0

так что на самом деле нет инструкции по возврату.

Теперь, если мы попытаемся запустить java Main мы получаем:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: (class: NoReturn, method: main signature: ([Ljava/lang/String;)V) Falling off the end of the code
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
        at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
        at java.lang.Class.getMethod0(Class.java:3018)
        at java.lang.Class.getMethod(Class.java:1784)
        at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Эта ошибка никогда не может произойти в Java в обычном режиме, поскольку компилятор Java добавляет неявный return в void методы для нас. Вот почему нам не нужно добавлять return нашим main методы. Вы можете проверить это с javap,

JVMs

VerifyError происходит, когда вы пытаетесь запустить определенные типы недопустимых файлов классов, как указано в JVMS 7, глава 4.5

JVMS говорит, что когда Java загружает файл, она должна выполнить серию проверок, чтобы убедиться, что файл класса в порядке, прежде чем запускать его.

Такие ошибки не могут быть сгенерированы в одном цикле компиляции и выполнения кода Java, потому что JVMS 7 4.10 говорит:

Хотя компилятор для языка программирования Java должен создавать только файлы классов, которые удовлетворяют всем статическим и структурным ограничениям [...]

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

В моем случае мне пришлось удалить этот блок:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
}

Он показывал ошибку рядом Fragment.showDialog() вызов метода.

После обновления Gradleв Android Studio 3.6.1 произошли сбои в API 19 в сборке выпуска.

Был Glide ошибка библиотеки. Решение - переписать proguard-rules.txt.

Также понижение Gradle работает (classpath 'com.android.tools.build:gradle:3.5.3'), но это устаревшее решение, не используйте его.

В моем случае мой проект A зависел от другого, скажем, X(A использовал некоторые классы, определенные в X). Поэтому, когда я добавил X в качестве ссылочного проекта в путь сборки A, я получил эту ошибку. Однако когда я удалил X в качестве ссылочного проекта и включил jar X в качестве одной из библиотек, проблема была решена.

Проверьте наличие нескольких версий одного и того же файла JAR на вашем пути к классам.

Например, у меня были opennlp-tools-1.3.0.jar и opennlp-tools-1.5.3.jar на моем пути к классам, и я получил эту ошибку. Решением было удалить opennlp-tools-1.3.0.jar.

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

Если вы переходите на java7 или используете java7, то, как правило, эту ошибку можно увидеть. Я сталкивался с вышеупомянутыми ошибками и много пытался выяснить причину, я бы предложил попробовать добавить аргумент JVM "-XX:-UseSplitVerifier" во время работы вашего приложения.

CGLIB < 2.2 с JRE > 6 может вызвать похожие ошибки, см. "Должен ли я обновиться до CGLIB 3.0?" и некоторые комментарии на весну SPR-9669.

Это особенно верно, когда на JRE 6 все работает нормально, и простой переход на JRE7 приводит к поломке.

Другой причиной этой ошибки может быть сочетание AspectJ <= 1.6.11 с JRE > 6.

Подробности смотрите в Eclipse Bug 353467 и в билете Kieker 307.

Это особенно верно, когда все работает нормально на JRE 6, а переход на JRE7 ломает вещи.

Эта страница может дать вам несколько советов - http://www.zanthan.com/itymbi/archives/000337.html

В теле этого метода может быть небольшая ошибка, которую javac не может обнаружить. Сложно диагностировать, если вы не разместите здесь весь метод.

Вы могли бы начать с объявления как можно большего числа переменных как final..., которые бы уловили ошибку, упомянутую на сайте zanthan, и в любом случае это часто хорошая практика.

Хотя причина, упомянутая Кевином, верна, но я обязательно проверю ниже, прежде чем перейти к чему-то другому:

  1. Проверить cglibs в моем классе
  2. Проверить hibernate версии в моем classpath.

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

java.lang.VerifyError означает, что ваш скомпилированный байт-код ссылается на то, что Android не может найти. Эта ошибка verifyError выдает меня только с помощью kitkat4.4 и более ранних версий, не включенных в вышеприведенную версию, даже если я запускал одну и ту же сборку на обоих устройствах. когда я использовал парсон джексона json более старой версии, он показывает java.lang.verifyerror

compile 'com.fasterxml.jackson.core:jackson-databind:2.2.+'
compile 'com.fasterxml.jackson.core:jackson-core:2.2.+'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.2.+'

Затем я изменил Dependancy до последней версии 2.2 до 2.7 без базовой библиотеки, тогда он работает. Это означает, что Методы и другое содержимое ядра перенесено в последнюю версию Databind2.7. Это исправить мои проблемы.

compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.0-rc3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0-rc3'

Напишите в файл:

{Wildfly-home}\modules\system\layers\base\org\picketbox\main 

в зависимости далее: <module name="sun.jdk"/>

Пожалуйста, удалите все ненужные файлы JAR и попробуйте запустить. и его работа для меня, я добавил jar-файл jcommons, а также другой jar-файл jcommons.1.0.14, так что удалите jcommons и его работу для меня

В моем случае я получал ошибку проверки с трассировкой ниже стека

jasperreports-server-cp-6.4.0-bin\buildomatic\build.xml:61: The following error occurred while executing this line:
TIB_js-jrs-cp_6.4.0_bin\jasperreports-server-cp-6.4.0-bin\buildomatic\bin\setup.xml:320: java.lang.VerifyError: (class: org/apache/commons/codec/binary/Base64OutputStream, method: <init> signature: (Ljava/io/OutputStream;ZI[B)V) Incompatible argument to function
    at com.jaspersoft.jasperserver.crypto.KeystoreManager.createKeystore(KeystoreManager.java:257)
    at com.jaspersoft.jasperserver.crypto.KeystoreManager.init(KeystoreManager.java:224)
    at com.jaspersoft.buildomatic.crypto.KeystoreTask.execute(KeystoreTask.java:64)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:435)
    at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:169)
    at org.apache.tools.ant.taskdefs.ImportTask.importResource(ImportTask.java:222)
    at org.apache.tools.ant.taskdefs.ImportTask.execute(ImportTask.java:163)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:435)
    at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:180)
    at org.apache.tools.ant.ProjectHelper.configureProject(ProjectHelper.java:93)
    at org.apache.tools.ant.Main.runBuild(Main.java:826)
    at org.apache.tools.ant.Main.startAnt(Main.java:235)
    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

Я решил проблему, удалив запись classpath для commons-codec-1.3.jar, в версии этого jar было несоответствие с тем, что поставляется с Jasper.

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