获取java.lang.VerifyError的原因

206

我正在调查以下 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 查看它,它给出了应该是的方法签名。

当我的其他同事检查代码、编译并部署时,他们遇到了同样的问题。当构建服务器获取代码并在开发或测试环境(HPUX)上部署时,会出现相同的错误。在运行Ubuntu的自动化测试机启动服务器期间,也会显示相同的错误。

应用程序的其余部分正常运行,只有一个servlet出了问题。任何指导都将非常有帮助。


1
我使用了错误版本的ComparisonFailure,导致出现了这个问题。找了好久才发现……真是太痛苦了。 - Tim Boland
1
我在使用Android Studio的即时运行(编译时热交换)时遇到了这个问题,关闭它就解决了。 - MainActivity
25个回答

203

java.lang.VerifyError可能是由于在编译时使用的库与运行时使用的库不同而导致的。

例如,当尝试运行一个使用Xerces 1编译的程序,但在类路径上找到了Xerces 2时,就会发生这种情况。在运行时,所需的类(在org.apache.*命名空间中)被找到,因此ClassNotFoundException不是结果。由于类和方法已经发生了变化,因此在运行时找到的方法签名与编译时的不匹配。

通常,编译器会标记方法签名不匹配的问题。当加载类时,JVM会再次验证字节码,并在字节码尝试执行不允许的操作时抛出VerifyError异常--例如调用返回String的方法并将其存储在一个保存List的字段中。


3
需要翻译的内容:One thing to add, sometimes it's the IDE's fault, or the device that the bytecode isn't right. Try restarting the IDE to get it to recognize the sync issue. Failing that delete and re-install the app. Rebooting the device may also help.有一点需要补充,有时候问题出在开发工具或设备上,导致字节码不正确。尝试重新启动开发工具以解决同步问题。如果还是不行,可以尝试删除并重新安装应用程序。重启设备也可能有所帮助。 - ima747
5
为了找出是哪个类导致了问题,请在VM参数中添加-verbose:class,然后寻找在它加载java.lang.VerifyError之前的类。这将会给出JAR文件的路径。使用javap命令并将其与你正在编译的类进行比较。我发现这很有用,因为报告错误的类不是真正的问题所在,而实际上是其中一个参数导致的。 - steinybot

23

java.lang.VerifyError是最糟糕的错误。

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

你是否100%确定这个类在应用程序中的classpath中不存在,也许在另一个jar包中?

此外,从你的堆栈跟踪信息中,源文件的字符编码(utf-8?)是否正确?


我确定它不会出现在其他地方。它有43Kb,这仍然是一个很大的类。 - Jeroen Wyseur
感谢您的帖子,在我的情况下,问题出在编码上:JasperReports XMl文件保存了一个编码和Java版本,您需要根据项目设置相应地进行设置(通过iReport)。这就是问题所在,感谢您提供编码方面的建议! :) - Tobias
这是我在 Android 测试中遇到的问题,使用 multidexing 解决了它。 - Prakash Nadar
谢谢 @p3t0r!对于我来说,类路径上加载了两个 ojdbc jars。移除一个解决了这个问题。 - Bhushan Karmarkar

11

正如Kevin Panko所说,这主要是因为库的更改。 因此,在某些情况下,对项目(目录)进行“清理”后再进行构建就可以解决问题。


9

你可以尝试使用-Xverify:all,它可以在加载字节码时验证,并且如果字节码无效,则有时会提供有用的错误消息。


请问,您如何应用“-Xverify:all”? - Cheok Yan Cheng

8

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

基本上,只有在编译器存在错误或类文件以某种方式损坏(例如通过故障的RAM或失败的硬盘)时,才会发生VerifyError。

尝试使用不同的JDK版本和不同的计算机进行编译。


8

2
链接已失效,请修复。谢谢。 - Mahdi Rashidi

5

1
Dalvik只是Java6的一个分支版本,因此没有Java7的功能可用! - Jeroen Wyseur

4

由于pack200对类文件进行了操纵,导致我遇到了这个问题。通过一些搜索,我发现了这个Java bug。基本上,设置--effort=4可以解决这个问题。

我使用的是Java 1.5.0_17,尽管它在我尝试的每个Java 1.5版本中都出现了。


3

你解决这个问题了吗,@MartinKonicek? - Abimbola Esuruoso

3

我曾通过替换代码中的内容来解决一个类似的java.lang.VerifyError问题。

        catch (MagickException e)

使用

        catch (Exception e)

MagickException 是在一个库项目中定义的(我所依赖的项目也依赖于该库)。

之后,我遇到了一个有关同一库中类的 java.lang.NoClassDefFoundError 错误(根据https://dev59.com/MV7Va4cB1Zd3GeqPHjQ0#9898820进行修复)。


1
这对我有用...但我真的想弄清楚除了“用毯子式异常替换我,我就能工作”之外的错误是什么。 - Alex Hart
@AlexHart 这是针对Android的,但是企业级Java可能适用相同的逻辑:https://dev59.com/4FoV5IYBdhLWcg3wJ8HD#36814155 - TWiStErRob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接