为什么java.lang.VerifyError会阻止编译成功?

时间:2014-09-28 12:23:52

标签: java jvm compatibility bytecode bytecode-manipulation

根据这个主题: Reasons of getting a java.lang.VerifyError

java.lang.VerifyError获取执行jvm的版本是否比用于编译的jvm更新。

我们始终可以使用以下jvm选项解决此问题:-XX:-UseSplitVerifier

据此:

https://stackoverflow.com/a/16467026/2674303

使用此选项是“非常安全”。

因此我不明白为什么java.lang.VerifyError是阻止成功编译的问题。请澄清。也许对于检测字节码的库来说是不安全的?

5 个答案:

答案 0 :(得分:5)

您链接的Q& A是指使用替代验证程序可以安全解决的特定类型的验证错误。但是,还有其他类型的验证错误,你不应该忽略......并且你不能以这种方式处理。

简而言之,关联问题中的建议一般不适用。一般来说:

  • 切换到替代验证程序可能不会有帮助。

  • 如果完全禁用验证程序,则可能会运行可能违反JVM运行时类型安全(等)约束的代码。这可能导致安全问题和/或堆损坏以及硬JVM崩溃。


如果您有需要建议的特定VerifyError,请包含完整的异常消息和堆栈跟踪,并描述它发生的情况。请注意,安德烈的答案是正确的,验证错误的常见原因是正在执行"字节码工程的代码中的错误。出于各种目的。通常,修复方法是更改​​为相应依赖项的不同版本。

答案 1 :(得分:1)

当您的字节代码以某种方式不正确时,会发生

VerifyError。例如,当它尝试从未初始化的变量读取或将原始值分配给类型Object的字段时。检测库可能存在导致生成这种格式错误的字节码的错误。如果您可以分享错误的确切详细信息,我们可能会更准确地说明确切原因。

答案 2 :(得分:1)

目标是强制工具和库在操作Java字节码时生成正确的StackMapTable属性,这样JVM就不必进行缓慢而复杂的type inferencing验证阶段,而只需要快速执行和简单的type checking阶段。

-XX:-UseSplitVerifier已在Java 8中弃用,它将不再有用。

答案 3 :(得分:1)

在JVM类加载期间抛出VerifyError,因此它出现在运行时级别,而不是编译级别。

  1. 我们并不总是可以使用旧的验证程序修复probem。有一个特殊情况,这有助于。它只有在类更老的验证程序时才有用,并且缺少在JVM 1.6中引入的StackMapTable,并且在JVM 1.7中是强制性的

  2. 如果你想摆脱VerifyError和UseSplitVerifier没有帮助,这意味着你的类从JVM的角度来看是不正确的。您仍然可以关闭整个验证,但这可能会导致问题。

  3. 当您不知道自己在做什么时,字节码操纵总是危险的。现在,主字节码操作库支持StackMapFrames计算,因此它们可以生成每个VM的字节码。但是,用户仍然可以生成在类文件级别上不正确的字节码,在这种情况下,JVM仍然会在加载时抛出VerifyError,SplitVerifier不会提供帮助。只有禁用验证才会强制VM加载该类,但在执行时可能会出现错误。

答案 4 :(得分:0)

你碰巧使用Java 7u65或8u11吗?如果是这样,那么本文可能与您的问题相关:http://www.takipiblog.com/oracles-latest-java-8-update-broke-your-tools-how-did-it-happen/

  

如果你最近一直在关注Java世界的新闻,   您可能听说过Oracle发布的最新Java 8版本,   Java 8u11(和Java 7u65),引入了错误并打破了一些流行   ZeroTurnaround的JRebel,Javassist,Google等第三方工具   Guice,甚至是Groovy本身。

     

这些错误突然出现的原因源于这一事实   最新更新中的字节码验证器有点严格   比以前的版本。与以前的版本不同,它没有   允许从分支代码中调用超级构造函数。