Causes d'obtention d'un java.lang.VerifyError

191

J'étudie ce qui suit 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)

Cela se produit lorsque le serveur jboss dans lequel le servlet est déployé est démarré. Il est compilé avec jdk-1.5.0_11 et j'ai essayé de le recompiler avec jdk-1.5.0_15 sans succès. C'est que la compilation fonctionne correctement mais lorsqu'elle est déployée, l'erreur java.lang.VerifyError se produit.

Lorsque j'ai changé le nom de la méthode et obtenu l'erreur suivante:

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)

Vous pouvez voir qu'une plus grande partie de la signature de la méthode est affichée.

La signature réelle de la méthode est

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

J'ai déjà essayé de le regarder avec javapet cela donne la signature de la méthode comme il se doit.

Lorsque mes autres collègues vérifient le code, le compilent et le déploient, ils ont le même problème. Lorsque le serveur de build récupère le code et le déploie sur des environnements de développement ou de test (HPUX), la même erreur se produit. Une machine de test automatisée exécutant Ubuntu montre également la même erreur lors du démarrage du serveur.

Le reste de l'application fonctionne correctement, seul ce servlet est en panne. Toute idée où chercher serait utile.

Jeroen Wyseur
la source
1
Je l'ai obtenu en utilisant la mauvaise version de ComparisonFailure. Il a fallu TOUJOURS pour trouver ... c'était douloureux
Tim Boland
1
Je l'ai eu lors de l'utilisation de l'exécution instantanée dans le studio Android (échange à chaud lors de la compilation). Le désactiver a fait le travail.
Serge

Réponses:

188

java.lang.VerifyError peut être le résultat lorsque vous avez compilé avec une bibliothèque différente de celle que vous utilisez au moment de l'exécution.

Par exemple, cela m'est arrivé en essayant d'exécuter un programme qui a été compilé avec Xerces 1, mais Xerces 2 a été trouvé sur le chemin de classe. Les classes requises (dans l' org.apache.*espace de noms) ont été trouvées au moment de l'exécution, ce ClassNotFoundExceptionn'est donc pas le cas. Il y avait eu des changements dans les classes et les méthodes, de sorte que les signatures de méthode trouvées au moment de l'exécution ne correspondaient pas à ce qui était présent lors de la compilation.

Normalement, le compilateur signalera les problèmes où les signatures de méthode ne correspondent pas. La JVM vérifiera à nouveau le bytecode lorsque la classe est chargée, et le lancera VerifyErrorlorsque le bytecode essaie de faire quelque chose qui ne devrait pas être autorisé - par exemple en appelant une méthode qui retourne Stringpuis stocke cette valeur de retour dans un champ contenant un List.

Kevin Panko
la source
3
Une chose à ajouter, c'est parfois la faute de l'EDI, ou du périphérique dont le bytecode n'est pas correct. Essayez de redémarrer l'EDI pour qu'il reconnaisse le problème de synchronisation. À défaut, supprimez et réinstallez l'application. Le redémarrage de l'appareil peut également aider.
ima747
2
Pour savoir quelle classe est le coupable, ajoutez l'argument VM -verbose:class, puis recherchez la classe juste avant son chargement java.lang.VerifyError. Cela aura le chemin vers le JAR. Utilisez javapet comparez cela à la classe avec laquelle vous compilez. J'ai trouvé cela utile car la classe signalée dans l'erreur n'était pas la raison pour laquelle c'était en fait l'un des arguments.
steinybot
21

java.lang.VerifyError sont les pires.

Vous obtiendrez cette erreur si la taille du bytecode de votre méthode dépasse la limite de 64 Ko; mais vous l'auriez probablement remarqué.

Êtes-vous sûr à 100% que cette classe n'est pas présente dans le classpath ailleurs dans votre application, peut-être dans un autre fichier jar?

De plus, à partir de votre stacktrace, le codage des caractères du fichier source ( utf-8?) Est-ce correct?

p3t0r
la source
Je suis sûr qu'il n'est pas présent ailleurs. C'est 43Ko, c'est encore une grande classe.
Jeroen Wyseur
Merci pour ce message, dans mon cas, c'était un encodage différent: les fichiers JasperReports XMl enregistrent un encodage et une version java, vous devez le définir en fonction des paramètres de votre projet (via iReport). C'était le problème ici, merci pour votre idée avec l'encodage! :)
Tobias
C'était mon problème pour les tests Android, le multidexing l'a corrigé.
Prakash Nadar
10

Comme l'a dit Kevin Panko, c'est principalement à cause du changement de bibliothèque. Donc, dans certains cas, un "nettoyage" du projet (répertoire) suivi d'une compilation fait l'affaire.

Couler
la source
9

Une chose que vous pouvez essayer est d'utiliser -Xverify:allqui vérifiera le bytecode au chargement et donne parfois des messages d'erreur utiles si le bytecode n'est pas valide.

Alex Miller
la source
8

VerifyError signifie que le fichier de classe contient un bytecode qui est syntaxiquement correct mais qui viole certaines restrictions sémantiques, par exemple une cible de saut qui traverse les limites de la méthode.

Fondamentalement, une VerifyError ne peut se produire que lorsqu'il y a un bogue du compilateur, ou lorsque le fichier de classe est corrompu d'une autre manière (par exemple par une RAM défectueuse ou un HD défaillant).

Essayez de compiler avec une autre version de JDK et sur une autre machine.

Michael Borgwardt
la source
5

Dans mon cas, mon projet Android dépend d'un autre projet Java compilé pour Java 7. java.lang.VerifyError disparu après avoir changé le niveau de conformité du compilateur de ce projet Java en 6.0

Plus tard, j'ai découvert qu'il s'agissait d'un problème Dalvik: https://groups.google.com/forum/?fromgroups#!topic/android-developers/sKsMTZ42pwE

Michal Vician
la source
1
Dalvik est juste une version branchée de Java6 donc aucune fonctionnalité Java7 n'est disponible!
Jeroen Wyseur
4

J'obtenais ce problème en raison de la destruction par pack200 d'un fichier de classe. Un peu de recherche a résolu ce bogue Java . Fondamentalement, le réglage a --effort=4fait disparaître le problème.

En utilisant java 1.5.0_17 (bien qu'il apparaisse dans chaque variante de java 1.5 je l'ai essayé).

Mike Miller
la source
3

J'ai corrigé un problème java.lang.VerifyError similaire en remplaçant

        catch (MagickException e)

avec

        catch (Exception e)

MagickException été défini dans un projet de bibliothèque (sur lequel mon projet a une dépendance).

Après cela, j'ai java.lang.NoClassDefFoundErrorune classe à propos de la même bibliothèque (corrigée selon https://stackoverflow.com/a/9898820/755804 ).

18446744073709551615
la source
1
Cela a fonctionné pour moi ... J'aimerais vraiment savoir quelle était l'erreur en plus de "remplacez-moi par une exception générale et je travaillerai".
Alex Hart
@AlexHart c'est pour Android, mais la même logique s'appliquerait probablement pour Java d'entreprise: stackoverflow.com/a/36814155/253468
TWiStErRob
2

Cela peut se produire sur Android lorsque vous essayez de charger une bibliothèque qui a été compilée avec le JDK d'Oracle.

Voici le problème du client HTTP Ning Async.

Martin Konicek
la source
Avez-vous encore trouvé une solution pour cela @MartinKonicek
Abimbola Esuruoso
2

Dans mon cas, j'ai dû supprimer ce bloc:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
}

Il montrait une erreur près de l' Fragment.showDialog()appel de méthode.

ViliusK
la source
2

Exemple minimal qui génère l'erreur

Une possibilité simple est d'utiliser Jasmin , ou d'éditer manuellement le bytecode avec un éditeur de fichier binaire.

Permet de créer une voidméthode sans returninstruction (générée par l' return;instruction en Java), ce que le JVMS considère comme illégal.

En Jasmin, nous pourrions écrire:

.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

Nous faisons alors javac Main.jet javap -v Maindit que nous avons compilé:

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

donc vraiment il n'y a aucune instruction de retour.

Maintenant, si nous essayons de courir, java Mainnous obtenons:

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)

Cette erreur ne peut jamais se produire en Java normalement, car le compilateur Java ajoute un implicite returnaux voidméthodes pour nous. C'est pourquoi nous n'avons pas besoin d'ajouter un returnà nos mainméthodes. Vous pouvez vérifier cela avec javap.

JVMS

VerifyError se produit lorsque vous essayez d'exécuter certains types de fichiers de classe illégaux comme spécifié par JVMS 7 chapitre 4.5

Le JVMS indique que lorsque Java charge un fichier, il doit exécuter une série de vérifications pour voir que le fichier de classe est OK avant de l'exécuter.

De telles erreurs ne peuvent pas être générées sur un seul cycle de compilation et d'exécution de code Java, car JVMS 7 4.10 dit :

Même si un compilateur pour le langage de programmation Java ne doit produire que des fichiers de classe qui satisfont toutes les contraintes statiques et structurelles [...]

Donc, pour voir un exemple d'échec minimal, nous devrons générer le code source sans javac.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
1

Cette page peut vous donner quelques conseils - http://www.zanthan.com/itymbi/archives/000337.html

Il peut y avoir un bug subtil dans le corps de cette méthode que javac ne parvient pas à repérer. Difficile à diagnostiquer sauf si vous publiez toute la méthode ici.

Vous pourriez commencer par déclarer autant de variables que possible comme finales ... cela aurait attrapé le bogue mentionné sur le site zanthan, et c'est souvent une bonne pratique de toute façon.

Lars Westergren
la source
1
Ce type a rencontré un bogue du compilateur en 2002, mais ce bogue a été corrigé depuis.
Kevin Panko
1

Eh bien dans mon cas, mon projet A était dépendant d'un autre, disons X (A utilisait certaines des classes définies dans X). Ainsi, lorsque j'ai ajouté X en tant que projet de référence dans le chemin de construction de A, j'ai eu cette erreur. Cependant, lorsque j'ai supprimé X en tant que projet référencé et inclus le jar de X comme l'une des bibliothèques, le problème a été résolu.

user2484130
la source
1

Recherchez plusieurs versions du même fichier jar sur votre chemin de classe.

Par exemple, j'avais opennlp-tools-1.3.0.jar et opennlp-tools-1.5.3.jar sur mon chemin de classe et j'ai obtenu cette erreur. La solution était de supprimer opennlp-tools-1.3.0.jar.

démongolem
la source
1

CGLIB <2.2 avec JRE> 6 pourrait déclencher des erreurs similaires, voir "Dois-je mettre à niveau vers CGLIB 3.0?" et quelques commentaires au printemps SPR-9669 .

Cela est particulièrement vrai lorsque tout fonctionne correctement sur JRE 6 et que le simple passage à JRE7 casse les choses.

Alexander Wessel
la source
1

Une autre raison de cette erreur peut être la combinaison de AspectJ <= 1.6.11 avec JRE> 6.

Voir Eclipse Bug 353467 et Kieker ticket 307 pour plus de détails.

Cela est particulièrement vrai lorsque tout fonctionne correctement sur JRE 6 et que le passage à JRE7 casse les choses.

Alexander Wessel
la source
1

Cela peut également arriver lorsque vous avez beaucoup d'importations de modules avec maven. Il y aura deux classes ou plus ayant exactement le même nom (même nom qualifié). Cette erreur est due à une différence d'interprétation entre la compilation et l'exécution.

Toumi
la source
1

Si vous migrez vers java7 ou utilisez java7, cette erreur est généralement visible. J'ai fait face aux erreurs ci-dessus et j'ai eu beaucoup de mal à trouver la cause principale, je suggère d'essayer d'ajouter l' argument JVM "-XX: -UseSplitVerifier" lors de l'exécution de votre application.

Ulhas N
la source
1

Après la mise Gradleà jour dans Android Studio 3.6.1, des plantages se sont produits sur l'API 19 dans la version de version.

Une erreur deGlide bibliothèque s'est produite . La solution consiste à réécrire proguard-rules.txt .

La rétrogradation Gradlefonctionne également ( classpath 'com.android.tools.build:gradle:3.5.3'), mais c'est une solution obsolète, ne l'utilisez pas.

CoolMind
la source
0

Bien que la raison mentionnée par Kevin soit correcte, je vérifierais certainement ci-dessous avant de passer à autre chose:

  1. Vérifiez le cglibsdans mon classpath.
  2. Vérifiez les hibernateversions dans mon classpath.

Il est fort probable qu'une version multiple ou conflictuelle de l'un des éléments ci-dessus puisse entraîner des problèmes inattendus comme celui en question.

Sandeep Jindal
la source
0

java.lang.VerifyError signifie que votre bytecode compilé fait référence à quelque chose qu'Android ne peut pas trouver. Cette verifyError ne me pose que kitkat4.4 et la version inférieure, pas dans la version ci-dessus, même si j'ai exécuté la même version dans les deux appareils. quand j'ai utilisé l'analyseur jackson json d'une version plus ancienne, il affiche 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.+'

Ensuite, j'ai changé la dépendance à la dernière version 2.2 à 2.7 sans la bibliothèque principale , puis cela fonctionne. ce qui signifie que les méthodes et autres contenus de core sont migrés vers la dernière version de Databind2.7 . Cela corrige mes problèmes.

compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.0-rc3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0-rc3'
anand krish
la source
Comment savoir quel JAR rechercher?
Siddharth
1
jackson-core: 2.2. + est devenu héritage. nous devons donc utiliser databind: 2.7.0-rc3, annotations: 2.7.0-rc3 ou la dernière version de celle-ci. Ce 2 suffit, évitez jackson-core: 2.2. +. J'ai eu une erreur de vérification à ce moment-là. lors de l'utilisation de la version 2.7+, il ne montre pas cette erreur
anand krish
0

veuillez supprimer tout fichier jar inutilisable et essayez de l'exécuter. et son travail pour moi j'ai ajouté un fichier jar jcommons et aussi un autre fichier jar jcommons.1.0.14 alors supprimez jcommons et cela fonctionne pour moi

Jat Rahul
la source
0

écrire sur fichier:

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

dans les dépendances ensuite: <module name="sun.jdk"/>

Eduardo Morales
la source
-1

Dans mon cas, j'obtenais une erreur de vérification avec la trace ci-dessous

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)

Je l'ai résolu en supprimant l'entrée de classpath pour commons-codec-1.3.jar, il y avait une incompatibilité dans la version de ce fichier avec celle fournie avec Jasper.

Aashirwad Sinha
la source