获取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) 

它发生在部署servlet的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查看它,并且给出了方法签名,因为它应该是。

当其他同事检查代码时,编译并部署代码,他们也有同样的问题。 当构build服务器拿起代码并将其部署在开发或testing环境(HPUX)上时,会发生相同的错误。 另外一台运行Ubuntu的自动化testing机在服务器启动过程中显示相同的错误

应用程序的其余部分运行正常,只有一个servlet出现故障。 任何想法在哪里看会有所帮助。

java.lang.VerifyError可能是针对不同于运行时使用的库编译的结果。

例如,当我尝试运行一个针对Xerces 1编译的程序时,发生了这种情况,但是在类path中find了Xerces 2。 所需的类(在org.apache.*名称空间中)是在运行时发现的,所以ClassNotFoundException 不是结果。 对类和方法进行了更改,以便在运行时find的方法签名与编译时的方法签名不匹配。

通常,编译器将标记方法签名不匹配的问题。 JVM将在加载类时再次validation字节码,并在字节码尝试做某些不应该被允许的事情时抛出VerifyError – 例如调用返回String的方法,然后将该返回值存储在包含List

java.lang.VerifyError是最差的。

如果你的方法的字节码大小超过了64kb的限制,你会得到这个错误; 但你可能已经注意到了。

你是否100%肯定这个类不在你的应用程序的其他地方的类path中,也许在另一个jar?

另外,从你的stacktrace,源文件的字符编码( utf-8 ?)是正确的吗?

正如凯文潘科所说,这主要是因为图书馆的变化。 所以在某些情况下,项目(目录)的“干净”后面跟着一个构build就行了。

我通过使我正在导入库的项目解决了Android上的这个错误,如下所述http://developer.android.com/tools/projects/projects-eclipse.html#SettingUpLibraryProject

以前,我只是引用该项目(而不是一个库),我得到了这个奇怪的VerifyError。

希望它可以帮助别人。

VerifyError表示类文件包含语法上正确的字节码,但违反了某些语义限制,例如跨越方法边界的跳转目标。

基本上,一个VerifyError只能发生在有编译器错误,或者类文件以其他方式被损坏(例如,通过错误的RAM或失败的HD)时。

尝试使用不同的JDK版本编译并在不同的机器上编译。

你可能会尝试的一件事是使用-Xverify:all这将validation加载字节码,有时如果字节码是无效的给出有用的错误消息。

在我的情况下,我的Android项目依赖于为Java 7编译的另一个Java项目。在将该Java项目的编译器符合级别更改为6.0后, java.lang.VerifyError消失

后来我发现这是一个Dalvik问题: https ://groups.google.com/forum/ ? fromgroups#! topic/ android-developers/ sKsMTZ42pwE

由于pack200损坏了一个类文件,我得到了这个问题。 有点search把这个java错误了。 基本上,设置--effort=4导致问题消失。

使用java 1.5.0_17(虽然它出现在Java 1.5的每一个单一变种,我试过了)。

我通过replace修复了一个类似的java.lang.VerifyError问题

  catch (MagickException e) 

  catch (Exception e) 

MagickException是在一个库项目(我的项目有一个依赖项)中定义的。

之后,我得到了一个java.lang.NoClassDefFoundError关于来自同一个库的类(根据https://stackoverflow.com/a/9898820/755804修复)。;

当您尝试加载针对Oracle JDK编译的库时,可能会发生在Android上。

这是 Ning Async HTTP客户端的问题 。

生成错误的最小示例

一个简单的可能性是使用Jasmin ,或者用二进制文件编辑器手动编辑字节码。

如果没有return指令(由Java中的return;语句生成),则创buildvoid方法,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.jjavap -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

当您尝试按照JVMS 7章4.5的规定运行某些types的非法类文件时,VerifyError发生

JVMS说,当Java加载一个文件时,它必须运行一系列的检查,以便在运行之前查看类文件是否正常。

这样的错误不能在Java代码的单个编译和运行周期中生成,因为JVMS 7 4.10说 :

尽pipeJava编程语言的编译器只能生成满足所有静态和结构约束的类文件,

因此,要看到一个最小的失败的例子,我们将需要生成没有javac的源代码。

这个页面可能会给你一些提示 – http://www.zanthan.com/itymbi/archives/000337.html

这个方法的主体中可能存在一个微妙的bug,javac无法识别。 除非您在这里发布整个方法,否则很难诊断。

你可以开始声明尽可能多的variables作为最终的…这将发现在zanthan网站上提到的bug,并且往往是一个很好的做法。

那么在我的情况下,我的项目A有一个依赖于另一个,说X(A使用一些在X中定义的类)。 所以当我在A的构buildpath中添加X作为参考项目时,我得到了这个错误。 然而,当我把X作为引用的项目,并将X的jar作为其中一个库时,问题就解决了。

在我的情况下,我不得不删除这个块:

 compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } 

它在Fragment.showDialog()方法调用附近显示错误。

检查你的classpath中同一个jar文件的多个版本。

例如,我在我的类path中打开了opennlp-tools-1.3.0.jar和opennlp-tools-1.5.3.jar,并得到这个错误。 解决的办法是删除opennlp-tools-1.3.0.jar。

CGLIB <2.2且JRE> 6可能触发类似的错误,请参阅“我应该升级到CGLIB 3.0吗?” 还有一些SPR-9669的评论。

当JRE 6上的所有东西都正常工作,并且简单地切换到JRE7时,情况尤其如此。

此错误的另一个原因可能是AspectJ <= 1.6.11与JRE> 6的组合。

有关详细信息,请参阅Eclipse错误353467和Kieker故障单307 。

当JRE 6上的所有东西都正常工作,并且转移到JRE7时,情况尤其如此。

在使用maven进行大量模块导入时,也可能发生这种情况。 将有两个或更多的类具有完全相同的名称(相同的限定名称)。 这个错误是由编译时和运行时之间的解释不同造成的。

如果你正在迁移到java7或使用java7然后通常可以看到这个错误。 我遇到了上面的错误,并努力找出根本原因,我会build议尝试添加“-XX:-UseSplitVerifier” JVM参数,同时运行您的应用程序。

虽然凯文提到的理由是正确的,但我肯定会检查下面,然后移动到别的东西:

  1. 检查我的类path中的cglibs
  2. 检查我的类path中的hibernate版本。

如果有多个或相互冲突的版本,可能会导致像所讨论的那样的意想不到的问题。

java.lang.VerifyError意味着你编译的字节码是指Android找不到的东西。 这个verifyError问题只与kitkat4.4和较小的版本不在上述版本 ,即使我在两个设备上运行相同的生成。 当我使用老版本的jackson jsonparsing器时,它显示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'