48

使用检测的 JDK7 编译代码存在已知的兼容性问题。至于http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

版本号为 51 的类文件是使用类型检查验证器专门验证的,因此这些方法必须在适当的时候具有 StackMapTable 属性。对于版本 50 的类文件,如果文件中的堆栈映射丢失或不正确,Hotspot JVM 将(并继续)故障转移到类型推断验证器。对于版本 51(Java SE 7 的默认版本)的类文件,不会发生此故障转移行为。任何修改版本 51 类文件中字节码的工具都必须确保更新堆栈图信息以与字节码保持一致才能通过验证。

解决方案是使用-XX:-UseSplitVerifier此处总结的: https ://community.oracle.com/blogs/fabriziogiudici/2012/05/07/understanding-subtle-new-behaviours-jdk-7

它有多安全?我想甲骨文把这个检查放在里面是有原因的。如果我不使用它,我可能会冒其他问题的风险。

使用会产生什么后果-XX:-UseSplitVerifier

谢谢,

彼得。

4

3 回答 3

54

简而言之,它非常安全。

从 Java 6 开始,Oracle 的编译器使用 StackMapTable 制作类文件。基本思想是编译器可以显式指定对象的类型,而不是让运行时来做。这在运行时提供了微小的加速,以换取编译期间的一些额外时间和编译的类文件(前面提到的 StackMapTable)的一些复杂性。

作为一项实验性功能,它在 Java 6 编译器中默认未启用。如果不存在 StackMapTable,则运行时默认验证对象类型本身。

直到 Java 7。Oracle 强制要求:编译器生成它们,运行时验证它们。如果 StackMapTable 不存在,它仍然使用旧的验证器......但仅限于 Java 6 或更早版本(版本 50)的类文件。使用 StackMapTable 需要 Java 7 类文件(版本 51),因此运行时不会对它们进行同样的处理。

如果您的类文件是在没有 StackMapTable 的情况下生成的,那么这只是一个问题。例如,如果您使用的是非 Oracle JVM。或者,如果你后来弄乱了字节码——比如将其与调试器、优化器或代码覆盖分析器一起使用。

但你可以绕过它!Oracle 的 JVM 提供了 -XX:+UseSplitVerifier 来强制运行时回退到旧的类型验证器。它不关心 StackMapTable。

在实践中,运行时速度和效率方面所希望的优化并没有实现:如果存在,还不足以让任何人注意到。由于新类型验证器不提供任何新功能(只是优化),因此将其关闭是非常安全的。

如果您搜索 JSR 202,Oracle 的解释位于http://www.oracle.com/technetwork/java/javase/compatibility-417013.html 。

于 2013-05-09T16:56:14.213 回答
24

是的——它是安全的。正如 Judebert 所说,它只是稍微减慢了类加载。

添加更多信息:StackMap 表到底是什么?好吧,字节码验证器需要对类文件中的代码进行两次传递,以验证正在传递和使用的数据类型是否正确。第一遍,速度较慢,对所有代码的分支进行流分析,以查看每个字节码指令的堆栈上可能有什么类型的数据。第二遍查看每条指令,看它是否可以有效地对所有这些类型进行操作。

这是关键:编译器已经拥有第一遍生成的所有信息 - 因此(在 Java 6 和 7 中)它将其存储在类文件的 StackMap 表中。

这加快了类加载,因为类加载器不必进行第一次传递。这就是为什么它被称为拆分验证器的原因,因为工作是在编译器和运行时加载机制之间拆分的。当您使用 -XX:-UseSplitVerifier 选项时,您告诉 Java 在类加载时进行两次传递(并忽略任何 StackMap 表)。许多产品(比如在加载时修改字节码的分析器)最初并不知道 StackMap 表,所以当他们在加载时修改类时,编译器的 StackMap 表已经过时并导致错误。

所以,总而言之, -XX:-UseSplitVerifier 选项会减慢类加载速度。它不会影响安全性、运行时性能或功能。

于 2013-10-15T14:13:44.387 回答
13

堆栈映射框架是在 Java 7 中添加的,“prashant”认为这个想法是有缺陷的,并建议开发人员总是使用-XX:-UseSplitVerifier标志来避免使用它们。

阅读更多:Java 7 字节码验证器:JVM 的巨大倒退

于 2013-03-26T13:14:05.560 回答