VerifyError: Nicht initialisiertes Objekt in Rückwärtszweig / JVM-Spezifikation 4.10.2.4 vorhanden

DasJVM Spec 4.10.2.4 Version 7, letzter Absatzsagt

Eine gültige Anweisungssequenz darf kein nicht initialisiertes Objekt auf dem Operandenstapel oder in einer lokalen Variablen am Ziel einer Rückwärtsverzweigung haben, wenn der spezielle Typ des nicht initialisierten Objekts mit einem anderen speziellen Typ als ihm selbst zusammengeführt wird

Hier ist ein Beispiel, das vom Prüfer abgelehnt wurde - ich vermute, dass es akzeptiert werden sollte:

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 ]

Die Fehlermeldung beklagt den Rückwärtssprungifne 5

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

Auf dem Stapel befindet sich tatsächlich ein nicht initialisiertes Objekt am Sprungziel. Es scheint mir jedoch, dass der "spezielle Typ des nicht initialisierten Objekts" mit sich selbst zusammengeführt wird, wie es die Spezifikation vorschreibt.

Ich denke, es gibt nur einen Stapelkartenrahmen, daher kann er nicht mit etwas anderem zusammengeführt werden.

Interessanterweise wurde die Einschränkung der Rückwärtsverzweigung im Internet aufgehobenJVM Spec Version 8.

Der Verifier in Java 8 VM lehnt das Beispiel jedoch weiterhin ab.

Habe ich die JVM-Spezifikation falsch gelesen oder sollte die Überprüfung des Beispiels wirklich fehlschlagen? Ich habe Versionen ausprobiert1.7.0_60-b19&nbsp;und1.8.0_05-b13.

Allgemeine Forschung

Das Problem taucht in Scala auf (Fehlerbericht). Um zu reproduzieren, nehmen Sie scala 2.11.1, vergewissern Sie sich, dass Sie sich auf einer JVM> = 1.7 befinden, und führen Sie Folgendes aus (stellen Sie sicher, dass Sie bestanden haben)-target:jvm-1.7&nbsp;zur 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

Wie oben erwähnt -JDK Bugreport hierIch hoffe, dort eine Antwort zu bekommen.

Der JDK-Fehler wurde in behobenJDK 8u25