VerifyError: existe um objeto não inicializado na ramificação reversa / JVM Spec 4.10.2.4

oJVM Spec 4.10.2.4 versão 7, último parágrafodiz

Uma sequência de instruções válida não deve ter um objeto não inicializado na pilha de operandos ou em uma variável local no destino de uma ramificação reversa se o tipo especial do objeto não inicializado for mesclado com um tipo especial que não seja ele próprio

Aqui está um exemplo rejeitado pelo verificador - suspeito que deve ser aceito:

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 ]

A mensagem de erro reclama sobre o salto para trásifne 5

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

De fato, há um objeto não inicializado na pilha no alvo do salto; no entanto, parece-me que o "tipo especial do objeto não inicializado" é mesclado consigo mesmo, conforme exigido pelas especificações.

Eu acho que existe apenas um quadro de mapa de pilha, então ele não pode ser mesclado com mais nada.

Curiosamente, a restrição de ramificações anteriores foi removida noJVM Spec versão 8.

No entanto, o Verificador na Java 8 VM ainda rejeita o exemplo.

Eu interpretei errado a especificação da JVM ou o exemplo realmente deve falhar na verificação? Eu tentei versões1.7.0_60-b19 e1.8.0_05-b13.

Pesquisa Geral

A questão aparece em Scala (relatório de erro) Para reproduzir, use o scala 2.11.1, verifique se você está em uma JVM> = 1.7 e execute o seguinte (certifique-se de passar-target:jvm-1.7 para 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 acima mencionado -Relatório de erros do JDK aqui, Espero obter uma resposta lá.

O bug do JDK foi corrigido noJDK 8u25

questionAnswers(0)

yourAnswerToTheQuestion