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
我正在尝试使用自定义编译器编译以下代码:
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