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