获取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├ow┬?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发生故障。
任何在哪里寻找的想法都会有所帮助。
解决方案
此页面可能会给我们一些提示
http://www.zanthan.com/itymbi/archives/000337.html
该方法的主体中可能存在一个细微的错误,javac无法发现该错误。除非我们在此处发布整个方法,否则很难诊断。
我们可以首先声明尽可能多的变量,这些变量将最终捕获zanthan网站上提到的错误,并且无论如何通常都是一个好习惯。
java.lang.VerifyError是最糟糕的。
如果方法的字节码大小超过64kb限制,则会出现此错误;但我们可能已经注意到了。
我们是否100%确定此类不在应用程序其他地方的类路径中(也许在另一个jar中)?
另外,从堆栈跟踪中,源文件的字符编码(utf-8)是否正确?
我们可能要尝试的一件事是使用-Xverify:all,它将在加载时验证字节码,如果字节码无效,有时会给出有用的错误消息。
由于pack200处理了一个类文件,我遇到了这个问题。进行一些搜索后发现此Java错误。基本上,设置--effort = 4
可以解决问题。
使用Java 1.5.0_17(尽管在我尝试过的Java 1.5的每个变体中都出现了)。
VerifyError表示该类文件包含语法正确的字节码,但违反了某些语义限制,例如跨越方法边界的跳转目标。
基本上,VerifyError仅在存在编译器错误或者类文件以其他某种方式损坏(例如,通过错误的RAM或者HD失败)时发生。
尝试使用其他JDK版本和其他计算机进行编译。
当我们针对与运行时使用的库不同的库进行编译时,可能会产生java.lang.VerifyError的结果。
例如,在尝试运行针对Xerces 1编译的程序时发生了这种情况,但是在类路径中找到了Xerces 2. 所需的类(在org.apache。*名称空间中)在运行时找到,因此不是ClassNotFoundException。对类和方法进行了更改,以便在运行时找到的方法签名与在编译时找到的方法签名不匹配。
通常,编译器会在方法签名不匹配的情况下标记问题。 JVM将在加载类时再次验证字节码,并在字节码尝试执行不应允许的操作时抛出" VerifyError"(例如,)。调用一个返回String的方法,然后将该返回值存储在保存List的字段中。