字节码指令 控制转移指令

控制转移指令是 Java 字节码指令的一类,用于实现程序的条件和无条件跳转。常见的控制转移指令包括:

goto:无条件跳转到另一个指定的位置;
ifeq, ifne, iflt, ifle, ifgt, ifge:根据栈顶的值,判断是否满足条件,如果满足,则跳转到指定位置;
tableswitch:根据栈顶的值,跳转到不同的位置,类似于 switch-case 语句;
lookupswitch:根据栈顶的值,跳转到不同的位置,类似于 switch-case 语句,但是 case 的值不是连续的。

以下是一些控制转移指令的示例:

// ifeq:如果栈顶的值为 0,则跳转到 Label_1
ifeq Label_1

// ifne:如果栈顶的值不为 0,则跳转到 Label_1
ifne Label_1

// iflt:如果栈顶的值小于 0,则跳转到 Label_1
iflt Label_1

// ifge:如果栈顶的值大于等于 0,则跳转到 Label_1
ifge Label_1

// tableswitch:根据栈顶的值跳转到不同的位置
tableswitch 0 to 2: {
  // case 0
  Label_0
  // case 1
  Label_1
  // case 2
  Label_2
}

// lookupswitch:根据栈顶的值跳转到不同的位置
lookupswitch {
  // case 0
  0: Label_0
  // case 1
  1: Label_1
  // case 2
  2: Label_2
}

以下是一些控制转移指令的示例:

goto指令:

public static int foo(int x) {
    if (x == 0) {
        x = 1;
    }
    return x + 1;
}

反编译后的字节码:

public static int foo(int);
  Code:
     0: iload_0
     1: ifne          6
     4: iconst_1
     5: istore_0
     6: iload_0
     7: iconst_1
     8: iadd
     9: ireturn

可以看到,如果x等于0,程序会跳转到第4条指令执行。

if指令:

public static void bar(int x) {
    if (x > 0) {
        System.out.println("x is positive");
    } else {
        System.out.println("x is non-positive");
    }
}

反编译后的字节码:

public static void bar(int);
  Code:
     0: iload_0
     1: ifgt          12
     4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
     7: ldc           #3                  // String x is non-positive
     9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    12: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    15: ldc           #5                  // String x is positive
    17: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    20: return

可以看到,如果x大于0,程序会跳转到第12条指令执行,否则会跳转到第4条指令执行。

tableswitch指令:

public static void baz(int x) {
    switch (x) {
        case 0:
            System.out.println("x is 0");
            break;
        case 1:
            System.out.println("x is 1");
            break;
        case 2:
            System.out.println("x is 2");
            break;
        default:
            System.out.println("x is not 0, 1, or 2");
            break;
    }
}

反编译后的字节码:

public static void baz(int);
  Code:
     0: iload_0
     1: tableswitch   { // 0 to 2
                   0: 28
                   1: 34
                   2: 40
             default: 46
        }
    28: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    31: goto          53
    34: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    37: goto          53
    40: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    43: goto          53
    46: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    49: goto          53
    52: return