VerifyError: el objeto no inicializado existe en la rama hacia atrás / JVM Spec 4.10.2.4

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

Una secuencia de instrucciones válida no debe tener un objeto no inicializado 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 distinto de sí mismo

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

public scala.Tuple2<scala.runtime.Null$, scala.runtime.Null
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 ]
gt; 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 del salto hacia atrásifne 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 no inicializado en la pila en el objetivo de salto; sin embargo, me parece que el "tipo especial del objeto no inicializado" 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 ramas hacia atrás se eliminó en elJVM Spec versión 8.

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

¿He leído mal la especificación JVM, o debería el ejemplo realmente fallar la verificación? Probé versiones1.7.0_60-b19 y1.8.0_05-b13.

Investigacion general

El problema aparece en Scala (informe de error) Para reproducir, tome scala 2.11.1, asegúrese de estar en una JVM> = 1.7 y ejecute lo siguiente (asegúrese 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 ha mencionado más arriba -Informe de errores JDK aquí, Espero obtener una respuesta allí.

El error JDK fue corregido enJDK 8u25

Respuestas a la pregunta(0)

Su respuesta a la pregunta