JVM: неверный индекс 1 в LocalVariableTable

Я пытаюсь скомпилировать следующий код с помощью специального компилятора:

public static void main([String] args)
{
    long i = 2L
    i *= 2L
    System out println i
}

Результат компиляции при использовании javapэтот байт-код:

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: ldc2_w        #14                 // long 2l
         3: lstore_1      
         4: lload_1       
         5: ldc2_w        #14                 // long 2l
         8: lmul          
         9: lstore_1      
        10: getstatic     #21                 // Field java/lang/System.out:Ljava/io/PrintStream;
        13: lload_1       
        14: invokevirtual #27                 // Method java/io/PrintStream.println:(J)V
        17: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      17     1     i   J
            0      17     0  args   [Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      args

Однако, когда я пытаюсь запустить Байт-код, JVM выдает ClassFormatError это читает Invalid index 1 in LocalVariableTable, Связано ли это с тем, что в LocalVariableTable слот 1 находится перед слотом 0?

РЕДАКТИРОВАТЬ:

Если я изменю long переменная к int, JVM не жалуется вообще, даже если LocalVariableTable все еще не отсортирован:

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: iconst_2      
         1: istore_1      
         2: iload_1       
         3: iconst_2      
         4: imul          
         5: istore_1      
         6: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
         9: iload_1       
        10: invokevirtual #25                 // Method java/io/PrintStream.println:(I)V
        13: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     1     i   I
            0      13     0  args   [Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      args

2 ответа

Решение

Похоже, я нашел ответ сам:

поскольку i это longтребуется два слота для хранения. Тем не менее, все еще можно поместить его в LocalVariableTable один раз, если вы рассчитываете его дважды при вычислении макс.

Это означает, что код работает, если байт-код выглядит так (locals=3):

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=5, locals=3, args_size=1
         0: ldc2_w        #14                 // long 2l
         3: lstore_1      
         4: lload_1       
         5: ldc2_w        #14                 // long 2l
         8: lmul          
         9: lstore_1      
        10: getstatic     #21                 // Field java/lang/System.out:Ljava/io/PrintStream;
        13: lload_1       
        14: invokevirtual #27                 // Method java/io/PrintStream.println:(J)V
        17: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      17     1     i   J
            0      17     0  args   [Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      args

Это, вероятно, не ответ (не могу комментировать это..:P)

Ваш пользовательский компилятор где-то не так..

  LocalVariableTable:
    Start  Length  Slot  Name   Signature
        0      17     1     i   J
        0      17     0  args   [Ljava/lang/String; 

Вы не можете иметь одинаковый стартовый индекс для 2 локальных переменных.

Java-компилятор дает вам:

 Start  Length  Slot  Name   Signature
     0      18     0  args   [Ljava/lang/String;
     4      14     1     i   J
Другие вопросы по тегам