2016-08-23 15 views
14

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).

Odpowiedz

5

Numery linii i zakres zmiennych lokalnych.

for pętli:

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 pętli:

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 pętla mniej odrębne linie kodu - co ma sens ponieważ zawija inicjalizacji i przyrost w jednej linii.

+2

Dlaczego skompilowany kod musi znać zakres zmiennej lokalnej? – shmosel

+0

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ąć. –

+0

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. –