Как декомпиляторы Java распознают цикл for из цикла while?
Рассмотрим эти два метода:
public static void forLoop(int start, int limit) {
for (int i = start; i < limit; i++) {
}
}
public static void whileLoop(int start, int limit) {
int i = start;
while (i < limit) {
i++;
}
}
При компиляции они создают байт-код (это подробный вывод javap
):
public static void forLoop(int, int);
descriptor: (II)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=2
0: iload_0
1: istore_2
2: iload_2
3: iload_1
4: if_icmpge 13
7: iinc 2, 1
10: goto 2
13: return
LineNumberTable:
line 6: 0
line 9: 13
LocalVariableTable:
Start Length Slot Name Signature
2 11 2 i I
0 14 0 start I
0 14 1 limit I
public static void whileLoop(int, int);
descriptor: (II)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=2
0: iload_0
1: istore_2
2: iload_2
3: iload_1
4: if_icmpge 13
7: iinc 2, 1
10: goto 2
13: return
LineNumberTable:
line 12: 0
line 13: 2
line 14: 7
line 16: 13
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 start I
0 14 1 limit I
2 12 2 i I
Как вы можете видеть, раздел кода для обоих этих методов точно такой же. Однако, когда я декомпилирую этот класс с помощью JD, он правильно производит:
public static void forLoop(int start, int limit) {
for (int i = start; i < limit; i++) {}
}
public static void whileLoop(int start, int limit)
{
int i = start;
while (i < limit) {
i++;
}
}
Как он мог это сделать? Байт-код этих методов точно такой же! Несмотря на то, что атрибуты LineNumberTable
и LocalVariableTable
были разными для каждого метода, я неохотно полагаю, что это причина, потому что это не требуемые атрибуты для атрибута Code
метода, который должен содержать (за раздел 4.7 Спецификации языка Java, Java SE 8 Edition).
Ответы
Ответ 1
Номера строк и область локальной переменной.
Цикл for
:
LineNumberTable:
line 6: 0
line 9: 13
LocalVariableTable:
Start Length Slot Name Signature
2 11 2 i I
0 14 0 start I
0 14 1 limit I
Цикл while
:
LineNumberTable:
line 12: 0
line 13: 2
line 14: 7
line 16: 13
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 start I
0 14 1 limit I
2 12 2 i I
В цикле for
меньше строк кода, что имеет смысл, поскольку оно завершает инициализацию и увеличение в одной строке.