J'enquête sur le Java.lang.VerifyError
suivant
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-à-dire que la compilation fonctionne correctement, mais une fois déployé, 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 que plus de signature de la méthode est affichée.
La signature de la méthode actuelle 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 javap
et cela donne la signature de la méthode comme il se doit.
Lorsque mes autres collègues extraient le code, le compilent et le déploient, ils ont le même problème. Lorsque le serveur de génération récupère le code et le déploie dans des environnements de développement ou de test (HPUX), la même erreur se produit. De plus, une machine de test automatique exécutant Ubuntu affiche la même erreur lors du démarrage du serveur.
Le reste de l'application fonctionne correctement, une seule servlet est en panne . Toute idée de recherche serait utile.
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é lorsque j'essayais d'exécuter un programme compilé avec Xerces 1, mais Xerces 2 était trouvé sur le chemin de classe. Les classes requises (dans l'espace de noms org.Apache.*
) ont été trouvées au moment de l'exécution. ClassNotFoundException
était doncnotle résultat. Des modifications ont été apportées aux classes et aux méthodes, de sorte que les signatures de méthode trouvées à l'exécution ne correspondent pas à celles qui existaient à 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 lors du chargement de la classe et lancera VerifyError
lorsque le bytecode tentera de faire quelque chose qui ne devrait pas être autorisé - par exemple. appeler une méthode qui retourne String
puis stocke cette valeur dans un champ qui contient List
.
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 auriez probablement remarqué cela.
Ê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 pile, le codage de caractères du fichier source (utf-8
?) Est-il correct?
Comme Kevin Panko l’a dit, c’est principalement à cause du changement de bibliothèque… .. Ainsi, dans certains cas, un «nettoyage» du projet (répertoire) suivi d’une construction fait l’essentiel.
J'ai corrigé cette erreur sur Android en faisant en sorte que le projet importait une bibliothèque, comme décrit ici http://developer.Android.com/tools/projects/projects-Eclipse.html#SettingUpLibraryProject
Auparavant, je ne faisais que référencer le projet (ne pas en faire une bibliothèque) et je recevais cet étrange VerifyError.
J'espère que ça aide quelqu'un.
VerifyError signifie que le fichier de classe contient un bytecode qui est syntaxiquement correct mais qui enfreint certaines restrictions sémantiques, par exemple. une cible de saut qui dépasse les limites de la méthode.
Fondamentalement, une erreur VerifyError ne peut se produire que s'il existe un bogue du compilateur ou lorsque le fichier de classe est corrompu d'une autre manière (par exemple, via RAM défectueux ou un disque dur défaillant).
Essayez de compiler avec une version différente du JDK et sur un autre ordinateur.
Une chose que vous pourriez essayer est d'utiliser -Xverify:all
qui vérifiera le code à la charge et donnera parfois des messages d'erreur utiles si le code est invalide.
Dans mon cas, mon projet Android dépend d'un autre projet Java compilé pour Java 7. Java.lang.VerifyError
a 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 avec Dalvik: https://groups.google.com/forum/?fromgroups#!topic/Android-developers/sKsMTZ42pwE
Je commençais à avoir ce problème à cause de la manipulation par Pack200 d'un fichier de classe. Un peu de recherche a tourné ce Java bug up. Fondamentalement, régler --effort=4
a permis de résoudre le problème.
Utilisation de Java 1.5.0_17 (bien que cela se soit produit dans toutes les variantes de Java 1.5, je l’ai essayé).
Cela peut arriver sous Android lorsque vous essayez de charger une bibliothèque compilée avec le JDK d'Oracle.
Voici le problème pour le client HTTP Ning Async.
J'ai résolu un problème similaire à Java.lang.VerifyError en remplaçant
catch (MagickException e)
avec
catch (Exception e)
où MagickException
a été défini dans un projet de bibliothèque (sur lequel mon projet a une dépendance).
Après cela, j'ai un Java.lang.NoClassDefFoundError
concernant une classe de la même bibliothèque (corrigé selon https://stackoverflow.com/a/9898820/755804 ).
Dans mon cas je devais enlever ce bloc:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
Il montrait une erreur près de l'appel de la méthode Fragment.showDialog()
.
Exemple minimal générant l'erreur
Une possibilité simple consiste à utiliser Jasmin , ou à modifier manuellement le bytecode avec un éditeur de fichier binaire.
Permet de créer la méthode void
sans instruction return
(générée par l'instruction return;
en Java), que le système JVMS dit illégale.
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 ensuite javac Main.j
et javap -v Main
dit 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 pas d'instruction de retour.
Maintenant, si nous essayons d'exécuter Java Main
, nous 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 normalement en Java, car le compilateur Java ajoute une méthode implicite return
à void
pour nous. C'est pourquoi nous n'avons pas besoin d'ajouter une return
à nos méthodes main
. Vous pouvez vérifier ceci 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 vérifier que le fichier de classe est correct 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 indique :
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 aurons besoin de générer le code source sans javac
.
Dans mon cas, mon projet A dépendait 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 génération de A, j'ai eu cette erreur. Cependant, lorsque j'ai supprimé X en tant que projet référencé et inclus le fichier jar de X en tant que bibliothèque, le problème a été résolu.
Cette page peut vous donner quelques indices. - http://www.zanthan.com/itymbi/archives/000337.html
Il peut y avoir un bogue subtil dans le corps de cette méthode que javac ne parvient pas à détecter. Difficile à diagnostiquer sauf si vous postez toute la méthode ici.
Vous pouvez commencer par déclarer autant de variables que possible en tant que final ... ce qui aurait attrapé le bogue mentionné sur le site zanthan et constitue souvent une bonne pratique de toute façon.
Si vous migrez vers Java7 ou utilisez Java7, cette erreur est généralement visible. J'ai fait face aux erreurs ci-dessus et ai beaucoup lutté pour trouver la cause du problème. Je vous conseillerais donc d'ajouter l'ajout de l'argument "-XX: -UseSplitVerifier" à la JVM lors de l'exécution de votre application.
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 eu cette erreur. La solution consistait à supprimer opennlp-tools-1.3.0.jar.
Une autre raison de cette erreur peut être la combinaison de AspectJ <= 1.6.11 avec JRE> 6.
Voir Bug Eclipse 353467 et Ticket Kieker 307 pour plus de détails.
Cela est particulièrement vrai lorsque tout fonctionne bien sur JRE 6 et que le passage à JRE7 casse les choses.
Cela peut également arriver lorsque vous avez beaucoup d'importations de modules avec maven . Deux ou plusieurs classes auront exactement le même nom (même nom qualifié) . Cette erreur résulte d'une différence d'interprétation entre les temps de compilation. et d'exécution.
CGLIB <2.2 avec JRE> 6 pourrait provoquer des erreurs similaires, voir "Devrais-je effectuer une mise à niveau vers CGLIB 3.0?" et quelques commentaires à Spring SPR-9669 .
Cela est particulièrement vrai lorsque tout fonctionne correctement sur JRE 6 et que le simple passage à JRE7 casse les choses.
Java.lang.VerifyError signifie que votre bytecode compilé fait référence à quelque chose qu'Android ne peut pas trouver. This verifyError Ne me lance qu'avec KitKat4.4 et une version inférieure ne figurant pas dans la version ci-dessus même si j'ai exécuté la même version dans les deux périphériques. quand j’ai utilisé l’analyseur jackson json de l’ancienne version, il montre 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 en 2.7 sans la bibliothèque core , 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'
veuillez supprimer tous les fichiers jar inutilisables et essayer de les exécuter. et son travail pour moi j'ai ajouté un fichier jcommons jar et aussi un autre fichier jcommons.1.0.14 jar afin de supprimer jcommons et son travail pour moi
Bien que la raison mentionnée par Kevin soit correcte, je vérifierais certainement ci-dessous avant de passer à autre chose:
cglibs
dans mon classpath. hibernate
dans mon classpath.Il est fort probable que la présence de versions multiples ou conflictuelles de l’un des éléments ci-dessus puisse entraîner des problèmes inattendus, comme celui en question.