JVM:LocalVariableTable 中的索引 1 无效

JVM: Invalid index 1 in LocalVariableTable

我正在尝试使用自定义编译器编译以下代码:

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

编译的结果是,当使用javap时,这个Bytecode:

  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

这可能不是答案(无法对此发表评论..: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

看来我自己找到了答案:

由于i是一个long,它需要两个槽来存储。不过放在LocalVariableTable中一次还是可以的,只要在计算max locals的时候算两次就可以了。

这意味着如果字节码看起来像这样,代码就可以工作 (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