Java反编译器如何从while循环中识别for循环?

Mar*_*ius 14 java decompiling

考虑这两种方法:

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++;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译时,它们会产生字节码(这是详细的输出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
Run Code Online (Sandbox Code Playgroud)

如您所见,这两种方法的代码部分完全相同.但是,当我使用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++;
  }
}
Run Code Online (Sandbox Code Playgroud)

怎么能这样做?这些方法的字节码完全相同!尽管每个方法的属性LineNumberTableLocalVariableTable属性都不同,但我不愿意相信这是因为那些不是Code包含方法属性的必需属性(根据Java语言规范的第4.7节,Java SE 8版)).

Jon*_*art 5

行号和局部变量范围.

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

for回路具有更少的代码线条分明的-这是有道理的,因为它包装了一个线上的初始化和增量.

  • 为什么编译代码需要知道局部变量范围? (2认同)