Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 7 String switch decompiled: unexpected instruction

I have decompiled a very simple class that uses the new Java 7 String Switch feature.

The class:

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;
        }

    }

}

Running the Java 7 "javap" against this class, generates an interesting set of instructions (the complete disassembled code is available here):

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

The "LOOKUPSWITCH" is an instruction used when the switch case is sparse and can replace the TABLESWITCH, that is the default instruction for "switch" statements.

So, the question is, why are we seeing a "LOOKUPSWITCH" followed by a "TABLESWITCH"?

Thanks Luciano

like image 974
Luciano Fiandesio Avatar asked Aug 05 '11 13:08

Luciano Fiandesio


1 Answers

With strings in switch finding the correct case statement is a 2 step process.

  1. Compute the hashcode of the switch string and look for a 'hashcode match' among the case statements, this is done via LOOKUPSWITCH. Note the large integer numbers under LOOKUPSWITCH, these are hashcodes of the strings in case statements.
  2. Now 2 strings can have the same hashcode, however unlikely it may be. Hence the actual string comparison must still take place. Hence once the hashcode is matched, the switch string is compared with the string in the matched case statement. The instructions between LOOKUPSWITCH and TABLESWITCH do exactly this. Once the match is confirmed, the code to be executed for the matched case statement is reached via TABLESWITCH.

Also note that it is useful to specify which compiler you used - javac or ECJ (Eclipse compiler for java). Both compilers may generate the bytecode differently.

like image 63
Deepak Azad Avatar answered Oct 28 '22 10:10

Deepak Azad