使用-XX有多安全:-UseSplitVerifier?

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

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

解决方法是使用-XX:-UseSplitVerifier ,如下所示: http -XX:-UseSplitVerifier

它有多安全? 我猜想甲骨文已经把这个检查的原因。 如果我不使用它,我可能冒着其他一些问题。

什么可能是使用-XX:-UseSplitVerifier后果-XX:-UseSplitVerifier

谢谢,

彼得。

总之,这是完全安全的。

自Java 6以来,Oracle的编译器已经使用StackMapTable创build了类文件。 其基本思想是编译器可以明确指定对象的types,而不是使运行时执行它。 这在运行时提供了一个小小的加速,换来了编译期间的一些额外时间,以及编译后的类文件(前面提到的StackMapTable)中的一些复杂性。

作为一个实验性的function,它在Java 6编译器中并未默认启用。 如果不存在StackMapTable,则运行时默认会validation对象types本身。

直到Java 7. Oracle强制它:编译器生成它们,运行时validation它们。 如果StackMapTable不在那里,它仍然使用旧的validation器…但只在来自Java 6或更早版本(版本50)的类文件中。 Java 7类文件(版本51)需要使用StackMapTable,因此运行时不会将它们剪切成相同的松弛。

这只是一个问题,如果你的类文件没有生成一个StackMapTable。 例如,如果您使用了非Oracle JVM。 或者,如果之后再与字节码混淆 – 就像使用debugging器,优化器或代码覆盖率分析器一样。

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

实际上,运行速度和效率上的希望优化还没有实现:如果存在,任何人都不会注意到。 由于新型validation器不提供任何新function(只是优化),closures它是完全安全的。

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

是的 – 这是安全的。 正如Judebert所说的那样,它只是稍微减缓了课堂上的负担。

添加更多信息:什么是一个StackMap表? 那么,字节码校验器需要对类文件中的代码进行两次遍历,以validation传递和使用的正确types的数据。 第一遍是较慢的,它对所有代码的分支进行stream分析,以查看每个字节码指令在栈上的数据types。 第二遍看每条指令,看看它是否可以有效地操作所有types。

下面是关键:编译器已经拥有了第一遍产生的所有信息 – 所以(在Java 6和7中)将它存储在类文件中的StackMap表中。

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

所以总结一下,-XX:-UseSplitVerifier选项减慢了类的加载速度。 它不影响安全性,运行时性能或function。

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

阅读更多: Java 7字节码validation器:JVM的巨大后退步骤