Scala VerifyError:反向分支/JVM规范4.10.2.4上存在未初始化的对象
这家公司说 如果未初始化对象的特殊类型与自身以外的特殊类型合并,则有效指令序列的操作数堆栈上或向后分支目标的局部变量中不得有未初始化对象 以下是一个被验证者拒绝的例子——我怀疑它应该被接受:Scala VerifyError:反向分支/JVM规范4.10.2.4上存在未初始化的对象,scala,jvm,jvm-crash,Scala,Jvm,Jvm Crash,这家公司说 如果未初始化对象的特殊类型与自身以外的特殊类型合并,则有效指令序列的操作数堆栈上或向后分支目标的局部变量中不得有未初始化对象 以下是一个被验证者拒绝的例子——我怀疑它应该被接受: public scala.Tuple2<scala.runtime.Null$, scala.runtime.Null$> apply(boolean); flags: ACC_PUBLIC Code: stack=4, locals=2, args_size=2
public scala.Tuple2<scala.runtime.Null$, scala.runtime.Null$> apply(boolean);
flags: ACC_PUBLIC
Code:
stack=4, locals=2, args_size=2
0: new #12 // class scala/Tuple2
3: dup
4: aconst_null
5: iload_1
6: ifne 5
9: aconst_null
10: invokespecial #16 // Method scala/Tuple2."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
13: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this LC;
0 14 1 x Z
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame */
offset_delta = 5
locals = [ class C, int ]
stack = [ uninitialized 0, uninitialized 0, null ]
在跳转目标的堆栈上确实有一个未初始化的对象;然而,在我看来,“未初始化对象的特殊类型”与自身合并,正如规范所要求的那样
我认为只有一个堆栈贴图帧,因此它不能与其他任何对象合并
有趣的是,对向后分支的限制在中被取消了
然而,Java8VM中的验证器仍然拒绝该示例
我是否误读了JVM规范,或者示例是否真的无法验证?我尝试了1.7.0\u 60-b19
和1.8.0\u 05-b13
版本
一般研究 这个问题出现在Scala()中。要复制,请使用scala 2.11.1,确保您在JVM>=1.7上,并运行以下操作(确保将
-target:JVM-1.7
传递给scala):
如上所述,我希望在那里得到答复
JDK bug在中得到了修复。在中,字节码似乎毫无用处。如果local1为0,它将无限循环,否则将忽略它。您使用的是哪个版本的JVM?位于的验证程序应该可以很好地接受您的代码(它甚至不包括您在源代码中发布的错误消息)。我使用的是
Java HotSpot(TM)64位服务器VM,Java 1.7.0_55
-将尝试其他一些。我认为您对规范的阅读是正确的,特殊类型在跳转之前是不变的。这段代码(和字节码)在我使用Scala 2.11.1版(Java HotSpot(TM)64位服务器虚拟机,Java 1.8.0)的Arch上确实有效。您看错了一章。JVM规范§4.10.2描述了适用于版本50的类型推断验证器StackMapTable
s是强制性的,不允许退回到类型推断验证器。因此,仅适用于(见前两句)。请注意,§4.9.2也包含向后分支限制,Java 8也已将其删除。但似乎§4.10.1从未有过这种限制。
java.lang.VerifyError: Uninitialized object exists on backward branch 5
Exception Details:
Location:
C.apply(Z)Lscala/Tuple2; @6: ifne
localhost:sandbox luc$ scala -target:jvm-1.7
Welcome to Scala version 2.11.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_55).
Type in expressions to have them evaluated.
Type :help for more information.
scala> class C {
| def apply(x: Boolean) = new Tuple2(null, {
| while (x) { }
| null
| })
| }
defined class C
scala> new C
java.lang.VerifyError: Uninitialized object exists on backward branch 5
Exception Details:
Location:
C.apply(Z)Lscala/Tuple2; @6: ifne
Reason:
Error exists in the bytecode
Bytecode:
0000000: bb00 0959 011b 9aff ff01 b700 0db0
Stackmap Table:
full_frame(@5,{Object[#2],Integer},{Uninitialized[#0],Uninitialized[#0],Null})
... 32 elided