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


191

Я расследую следующее 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 показывает ту же ошибку при запуске сервера.

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


1
Я получил это от использования неправильной версии ComparisonFailure. Взял НАВСЕГДА, чтобы найти ... это было больно
Тим Боланд

1
Я получил это при использовании Instant Run в Android Studio (горячая загрузка при компиляции). Выключение сделало работу.
Серж

Ответы:


188

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

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

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


3
Одна вещь, которую нужно добавить, иногда это ошибка IDE или устройство, в котором неправильный байт-код. Попробуйте перезапустить среду IDE, чтобы она распознала проблему синхронизации. В противном случае удалите и переустановите приложение. Перезагрузка устройства также может помочь.
ima747

2
Чтобы выяснить, какой класс является виновником, добавьте аргумент VM, -verbose:classа затем найдите класс непосредственно перед его загрузкой java.lang.VerifyError. Это будет путь к банке. Используйте javapи сравните это с классом, с которым вы компилируете. Я нашел это полезным, так как класс, о котором сообщалось в ошибке, не был причиной, по которой он был одним из аргументов.
Steinybot

21

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

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

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

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


Я уверен, что это не присутствует где-то еще. Это 43Kb, это все еще большой класс.
Джероен Вайзер,

Спасибо за этот пост, в моем случае это была другая кодировка: файлы JasperReports XMl сохраняют кодировку и версию Java, вы должны установить это в соответствии с настройками вашего проекта (через iReport). В этом была проблема, спасибо за вашу идею с кодировкой! :)
Тобиас

Это было моей проблемой для тестов Android, мультидексирование это исправило.
Пракаш Надар

10

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


9

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


8

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

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

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


2
ссылка больше не доступна, пожалуйста, исправьте это. спасибо
Махди Рашиди

8

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

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

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


5

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

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


1
Dalvik - это просто разветвленная версия Java6, поэтому функции Java7 недоступны!
Джероен Визер

4

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

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


3

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

        catch (MagickException e)

с участием

        catch (Exception e)

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

После этого я получил java.lang.NoClassDefFoundErrorоколо класса из той же библиотеки (исправлено в соответствии с https://stackoverflow.com/a/9898820/755804 ).


1
Это сработало для меня ... Я действительно хотел бы выяснить, в чем ошибка, кроме "замените меня общим исключением, и я буду работать".
Алекс Харт

@AlexHart это для Android, но, вероятно, та же логика будет применима и для корпоративной Java: stackoverflow.com/a/36814155/253468
TWiStErRob


2

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

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
}

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


2

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

Одна простая возможность - использовать 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.


1

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

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

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


1
Этот парень обнаружил ошибку компилятора еще в 2002 году, но эта ошибка была исправлена ​​с тех пор.
Кевин Панко

1

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


1

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

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




1

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


1

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


1

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

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

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


0

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

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

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


0

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'

Как вы знаете, какой JAR искать?
Сиддхарт

1
Джексон-ядро: 2.2. + это стало наследием. поэтому нам нужно использовать databind: 2.7.0-rc3, аннотации: 2.7.0-rc3 или более позднюю версию, чем эта. Этого 2 достаточно, избегайте Jackson-Core: 2.2. +. К тому времени я получил подтверждение. при использовании 2.7+ версии он не показывает , что ошибка
Ананд Криш

0

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



-1

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

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.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.