我正在调查以下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出了问题。 知道去哪里找会很有帮助。


当前回答

生成错误的最小示例

一种简单的方法是使用Jasmin,或者使用二进制文件编辑器手动编辑字节码。

让我们创建一个没有return指令的void方法(由return生成;语句),jvm认为这是非法的。

在Jasmin中我们可以这样写:

.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。javap -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编译器为我们添加了一个隐式返回void方法。这就是为什么我们不需要在主方法中添加return。你可以用javap检查。

JVMS

当您尝试运行JVMS 7第4.5章指定的某些类型的非法类文件时,将发生VerifyError

jvm说,当Java加载一个文件时,它必须在运行类文件之前运行一系列检查,以确定类文件是OK的。

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

尽管Java编程语言的编译器必须只生成满足所有静态和结构约束的类文件[…] ]

因此,为了查看最小失败示例,我们需要在不使用javac的情况下生成源代码。

其他回答

我得到这个问题,由于pack200 manging一个类文件。稍微搜索一下就找到了这个java错误。基本上,设置——effort=4可以解决问题。

使用java 1.5.0_17(尽管它出现在我尝试的每一个java 1.5变体中)。

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

详细信息请参见Eclipse Bug 353467和Kieker ticket 307。

当在JRE 6上一切正常,而迁移到JRE7时,情况尤其如此。

生成错误的最小示例

一种简单的方法是使用Jasmin,或者使用二进制文件编辑器手动编辑字节码。

让我们创建一个没有return指令的void方法(由return生成;语句),jvm认为这是非法的。

在Jasmin中我们可以这样写:

.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。javap -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编译器为我们添加了一个隐式返回void方法。这就是为什么我们不需要在主方法中添加return。你可以用javap检查。

JVMS

当您尝试运行JVMS 7第4.5章指定的某些类型的非法类文件时,将发生VerifyError

jvm说,当Java加载一个文件时,它必须在运行类文件之前运行一系列检查,以确定类文件是OK的。

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

尽管Java编程语言的编译器必须只生成满足所有静态和结构约束的类文件[…] ]

因此,为了查看最小失败示例,我们需要在不使用javac的情况下生成源代码。

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

在该方法的主体中可能存在javac未能发现的微妙错误。很难诊断,除非你把整个方法贴在这里。

你可以先声明尽可能多的变量作为final…这将捕获zanthan网站上提到的bug,而且通常是一个很好的实践。

在我的例子中,我的项目A依赖于另一个项目,比如X(A使用了X中定义的一些类),所以当我在A的构建路径中添加X作为参考项目时,我得到了这个错误。然而,当我删除X作为引用项目,并将X的jar作为库之一时,问题就解决了。