Uważają, że te dwie metody:W jaki sposób dekompilatory Java rozpoznają pętlę for z pętli 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++;
}
}
Kiedy skompilowany produkują kodu bajtowego (to gadatliwe wyjście 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
Jak widać, część kodu dla obu z nich metody są dokładnie takie same, jak . Jednak, kiedy dekompilować tej klasy przy użyciu JD, że prawidłowo produkuje:
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++;
}
}
Jak było w stanie to zrobić? Kod bajtowy tych metod jest dokładnie taki sam! Pomimo faktu, że atrybuty LineNumberTable
i LocalVariableTable
były różne dla każdej metody, jestem niechętny, aby sądzić, że jest to powód, ponieważ nie są to wymagane atrybuty dla atrybutu Code
metody (na).
Dlaczego skompilowany kod musi znać zakres zmiennej lokalnej? – shmosel
Nie sądzę, że * potrzebuje *, ale z pewnością pomaga w debugowaniu. Wyobrażam sobie, że to jedyny powód, dla którego tam jest. Są prawdopodobnie narzędzia, które mogą go usunąć. –
Domyślam się, że pomaga to wydajniej wykorzystywać listę zmiennych lokalnych. Na przykład, jeśli lokalna zmienna przechowywana w indeksie 2 wypadnie poza zakresem, kompilator wie, że może ponownie użyć indeksu 2 dla innej zmiennej lokalnej. Jeśli indeksy nie były ponownie używane, "maks. Locals" dla każdej metody byłyby równoważne liczbie zmiennych lokalnych zadeklarowanych w metodzie, * nie * maksymalnej liczbie zmiennych lokalnych widocznych w pewnym zakresie w ramach metody. –