JVM:LocalVariableTable中的索引1无效

时间:2015-02-27 08:30:56

标签: java jvm java-bytecode-asm

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

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 个答案:

答案 0 :(得分:0)

这可能不是答案(不能评论这个......: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

答案 1 :(得分:0)

看起来我自己找到了答案:

由于ilong,因此需要存储两个广告位。但是,只要在计算最大本地时计算两次就可以将它放在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