Java 7 String switch反编译:意外指令

Luc*_*sio 14 java decompiling switch-statement java-7

我已经反编译了一个使用新的Java 7字符串切换功能的非常简单的类.

班级:

public class StringSwitch {

    public static void main(String[] args) {

        final String color = "red";
        switch (color) {
            case "red":
                System.out.println("IS RED!");
                break;
            case "black":
                System.out.println("IS BLACK");
                break;
            case "blue":
                System.out.println("IS BLUE");
                break;
            case "green":
                System.out.println("IS GREEN");
                break;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

针对此类运行Java 7"javap",会生成一组有趣的指令(完整的反汇编代码可在此处获得):

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=2, locals=4, args_size=1
        ...
        12: lookupswitch  { // 4

                  112785: 56

                 3027034: 84

                93818879: 70

                98619139: 98
                 default: 109
            }
        56: aload_2       
        57: ldc           #2                  // String red
        ...       
       110: tableswitch   { // 0 to 3

                       0: 140

                       1: 151

                       2: 162

                       3: 173
                 default: 181
            }
       140: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
       143: ldc           #9                  // String IS RED!
       ...
       181: return
Run Code Online (Sandbox Code Playgroud)

"LOOKUPSWITCH"是一个指令,当开关盒稀疏时可以替换TABLESWITCH,这是"switch"语句的默认指令.

所以,问题是,为什么我们看到"LOOKUPSWITCH"后跟"TABLESWITCH"?

谢谢卢西亚诺

Dee*_*zad 17

使用switch中的字符串查找正确的case语句是一个两步过程.

  1. 计算switch字符串的hashcode并在case语句中查找'hashcode match',这是通过LOOKUPSWITCH完成的.注意LOOKUPSWITCH下的大整数,这些是case语句中字符串的哈希码.
  2. 现在2个字符串可以具有相同的哈希码,但不太可能.因此,仍然必须进行实际的字符串比较.因此,一旦匹配哈希码,就将交换机字符串与匹配的case语句中的字符串进行比较.LOOKUPSWITCH和TABLESWITCH之间的指令就是这样做的.确认匹配后,将通过TABLESWITCH访问匹配的case语句要执行的代码.

另请注意,指定您使用的编译器是有用的 - javac或ECJ(Java的Eclipse编译器).两个编译器都可能以不同方式生成字节码.