我正在尝试使用自定义编译器编译以下代码:
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
答案 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)
看起来我自己找到了答案:
由于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