scala jvm jvm-crash

scala - VerifyError: existe un objeto sin inicializar en la rama anterior/especificación de JVM 4.10.2.4



jvm-crash (0)

La JVM Spec 4.10.2.4 versión 7, último párrafo , dice

Una secuencia de instrucciones válida no debe tener un objeto sin inicializar en la pila de operandos o en una variable local en el destino de una rama hacia atrás si el tipo especial del objeto no inicializado se fusiona con un tipo especial que no sea él mismo.

Aquí hay un ejemplo rechazado por el verificador: sospecho que debería ser aceptado:

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 ]

El mensaje de error se queja sobre el salto hacia atrás ifne 5

java.lang.VerifyError: Uninitialized object exists on backward branch 5 Exception Details: Location: C.apply(Z)Lscala/Tuple2; @6: ifne

De hecho, hay un objeto sin inicializar en la pila en el objetivo de salto; sin embargo, me parece que el "tipo especial del objeto sin inicializar" se fusiona consigo mismo, tal como lo requiere la especificación.

Creo que solo hay un marco de mapa de pila, por lo que no se puede combinar con nada más.

Curiosamente, la restricción de las ramas hacia atrás se eliminó en la versión 8 de la especificación JVM .

Sin embargo, el Verificador en Java 8 VM todavía rechaza el ejemplo.

¿He leído mal la especificación de JVM, o el ejemplo realmente falla en la verificación? 1.7.0_60-b19 versiones 1.7.0_60-b19 y 1.8.0_05-b13 .

Investigación general

El problema aparece en Scala ( bugreport ). Para reproducirlo, toma scala 2.11.1, asegúrate de estar en una JVM> = 1.7 y ejecuta lo siguiente (asegúrate de pasar -target:jvm-1.7 a scala):

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

Como se mencionó anteriormente, el informe de errores de JDK aquí , espero obtener una respuesta allí.

El error JDK fue corregido en JDK 8u25