出现 java.lang.VerifyError 的原因
-
01-07-2019 - |
题
我正在调查以下内容 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 出现故障。任何去哪里寻找的想法都会有帮助。
解决方案
java.lang.VerifyError
当您针对与运行时使用的库不同的库进行编译时,可能会出现这样的结果。
例如,当我尝试运行针对 Xerces 1 编译的程序时,就发生了这种情况,但在类路径上发现了 Xerces 2。所需课程(在 org.apache.*
命名空间)是在运行时找到的,所以 ClassNotFoundException
曾是 不是 结果。类和方法发生了更改,因此运行时找到的方法签名与编译时的方法签名不匹配。
通常,编译器会标记方法签名不匹配的问题。当类被加载时,JVM会再次验证字节码,并抛出异常 VerifyError
当字节码试图做一些不应该被允许的事情时——例如调用一个返回的方法 String
然后将该返回值存储在包含 List
.
其他提示
java.lang.VerifyError
是最糟糕的。
如果您的方法的字节码大小超过 64kb 限制,您将收到此错误;但你可能已经注意到了。
您是否 100% 确定该类不存在于应用程序其他位置的类路径中,也许存在于另一个 jar 中?
另外,从您的堆栈跟踪中,是源文件的字符编码(utf-8
?) 那是对的吗?
正如 Kevin Panko 所说,这主要是因为库的变化。因此,在某些情况下,“清理”项目(目录)然后进行构建就可以解决问题。
我通过将项目导入库来修复 Android 上的此错误,如此处所述 http://developer.android.com/tools/projects/projects-eclipse.html#SettingUpLibraryProject
以前,我只是引用该项目(没有将其设为库),并且收到了这个奇怪的VerifyError。
希望它能帮助某人。
您可以尝试的一件事是使用 -Xverify:all
它将在加载时验证字节码,如果字节码无效,有时会给出有用的错误消息。
verifyError 意味着类文件包含语法正确但违反了某些语义限制的字节码,例如跨越方法边界的跳转目标。
基本上,只有当存在编译器错误或类文件以其他方式损坏时(例如,由于 RAM 故障或 HD 故障)。
尝试使用不同的 JDK 版本并在不同的计算机上进行编译。
就我而言,我的 Android 项目依赖于另一个为 Java 7 编译的 Java 项目。 java.lang.VerifyError
当我将该 Java 项目的编译器合规级别更改为 6.0 后消失
后来我发现这是Dalvik的问题: https://groups.google.com/forum/?fromgroups#!topic/android-developers/sKsMTZ42pwE
由于 pack200 损坏了类文件,我遇到了这个问题。一些搜索变成了这个 java错误 向上。基本上,设置 --effort=4
导致问题消失。
使用java 1.5.0_17(尽管它出现在我尝试过的java 1.5的每个变体中)。
我通过替换修复了类似的 java.lang.VerifyError 问题
catch (MagickException e)
和
catch (Exception e)
在哪里 MagickException
是在库项目中定义的(我的项目有依赖项)。
之后我有一个 java.lang.NoClassDefFoundError
关于来自同一个库的类(根据 https://stackoverflow.com/a/9898820/755804 ).
当您尝试加载针对 Oracle JDK 编译的库时,在 Android 上可能会发生这种情况。
这是问题所在 适用于 Ning 异步 HTTP 客户端。
就我而言,我必须删除此块:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
附近显示错误 Fragment.showDialog()
方法调用。
生成错误的最小示例
一种简单的可能性是使用 茉莉花, ,或使用二进制文件编辑器手动编辑字节码。
让我们创建 void
方法没有 return
指令(由生成 return;
Java 中的声明),JVMS 认为这是非法的。
在 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.j
和 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 编译器添加了一个隐式的 return
到 void
为我们提供的方法。这就是为什么我们不需要添加 return
给我们的 main
方法。你可以检查一下 javap
.
JVMS
当您尝试运行指定的某些类型的非法类文件时,会发生验证错误 JVMS 7 第 4.5 章
JVMS 表示,当 Java 加载文件时,它必须在运行之前运行一系列检查以查看类文件是否正确。
此类错误不会在 Java 代码的单个编译和运行周期中生成,因为 JVMS 7 4.10 说:
尽管 Java 编程语言的编译器必须只生成满足所有静态和结构约束的类文件 [...]
因此,要查看最小故障示例,我们需要生成源代码而不需要 javac
.
此页面可能会给您一些提示 -http://www.zanthan.com/itymbi/archives/000337.html
该方法的主体中可能存在 javac 无法发现的细微错误。除非您在此处发布整个方法,否则很难诊断。
您可以首先声明尽可能多的变量作为最终...这会捕获 zanthan 网站上提到的错误,而且无论如何通常都是一个很好的做法。
就我而言,我的项目 A 依赖于另一个项目,比如 X(A 正在使用 X 中定义的一些类)。因此,当我在 A 的构建路径中添加 X 作为参考项目时,出现此错误。然而,当我删除 X 作为引用的项目并将 X 的 jar 作为库之一包含时,问题就解决了。
检查类路径上同一 jar 文件的多个版本。
例如,我的类路径中有 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 和 凯克门票 307 了解详情。
当 JRE 6 上一切正常并且迁移到 JRE7 会出现问题时尤其如此。
当您使用 Maven 导入大量模块时,也可能会发生这种情况。将有两个或多个类具有完全相同的名称(相同的限定名称)。该错误是由于编译时和运行时之间的解释差异造成的。
如果您正在迁移到 java7 或使用 java7,那么通常会看到此错误。我遇到了上述错误,并努力找出根本原因,我建议尝试添加 “-XX:-使用SplitVerifier” 运行应用程序时的 JVM 参数。
虽然凯文提到的原因是正确的,但在转向其他内容之前我肯定会检查以下内容:
- 检查
cglibs
在我的类路径中。 - 检查
hibernate
我的类路径中的版本。
拥有上述任何一项的多个或冲突版本很可能会导致意外问题,例如所讨论的问题。
java.lang.VerifyError 意味着您编译的字节码引用了 Android 无法找到的内容。这个 verifyError 只向我发出 kitkat4.4及以下版本不在以上版本中 即使我在两个设备中运行相同的版本。当我使用旧版本的 jackson json 解析器时,它显示 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.+'
然后我将依赖项更改为 最新版本2.2至2.7 没有 核心库, ,然后就可以了。这意味着方法和其他内容 核 已迁移至最新版本 数据绑定2.7. 。这解决了我的问题。
compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.0-rc3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0-rc3'
请删除所有无法使用的 jar 文件并尝试运行。它对我有用,我添加了一个 jcommons jar 文件和另一个 jcommons.1.0.14 jar 文件,所以删除 jcommons 及其对我的工作
就我而言,我收到以下堆栈跟踪的验证错误
jasperreports-server-cp-6.4.0-bin\buildomatic\build.xml:61: The following error occurred while executing this line:
TIB_js-jrs-cp_6.4.0_bin\jasperreports-server-cp-6.4.0-bin\buildomatic\bin\setup.xml:320: java.lang.VerifyError: (class: org/apache/commons/codec/binary/Base64OutputStream, method: <init> signature: (Ljava/io/OutputStream;ZI[B)V) Incompatible argument to function
at com.jaspersoft.jasperserver.crypto.KeystoreManager.createKeystore(KeystoreManager.java:257)
at com.jaspersoft.jasperserver.crypto.KeystoreManager.init(KeystoreManager.java:224)
at com.jaspersoft.buildomatic.crypto.KeystoreTask.execute(KeystoreTask.java:64)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:435)
at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:169)
at org.apache.tools.ant.taskdefs.ImportTask.importResource(ImportTask.java:222)
at org.apache.tools.ant.taskdefs.ImportTask.execute(ImportTask.java:163)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:435)
at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:180)
at org.apache.tools.ant.ProjectHelper.configureProject(ProjectHelper.java:93)
at org.apache.tools.ant.Main.runBuild(Main.java:826)
at org.apache.tools.ant.Main.startAnt(Main.java:235)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
我通过删除 commons-codec-1.3.jar 的类路径条目解决了这个问题,这个 jar 的版本与 Jasper 附带的版本不匹配。