Search code examples
javastringoptimizationequalitystring-interning

Java - strings equals when decompiled


I decompiled some Java code the other day and found this:

String s1 = "something";
String s2 = "something_else";

if (s1 == s2) {
// Path 1
} else {
// Path 2
}

Obviously using '==' to test for string equality is bad

But I wondered - This code has been compiled and decompiled. If all the strings have been defined at compile time and interned and the code has been compiled - is it possible that s1.equals(s2) could have been optimized down to 's1 == s2'?


Solution

  • I highly doubt it. As a rule, Java compilers do very little by way of bytecode optimization, leaving optimization to the JIT phase.

    I've experimented with this a little, and my compiler doesn't do anything interesting with the following:

    public class Clazz {
    
        public static void main(String args[]) {
            final String s1 = "something";
            final String s2 = "something_else";
            if (s1.equals(s2)) {
                System.out.println("yes");
            } else {
                System.out.println("no");
            }
        }
    
    }
    

    This would probably be the easiest case to optimize. However, the bytecodes are:

      public static void main(java.lang.String[]);
        Code:
           0: ldc           #16                 // String something
           2: astore_1      
           3: ldc           #18                 // String something_else
           5: astore_2      
           6: ldc           #16                 // String something
           8: ldc           #18                 // String something_else
          10: invokevirtual #20                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
          13: ifeq          27
          16: getstatic     #26                 // Field java/lang/System.out:Ljava/io/PrintStream;
          19: ldc           #32                 // String yes
          21: invokevirtual #34                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          24: goto          35
          27: getstatic     #26                 // Field java/lang/System.out:Ljava/io/PrintStream;
          30: ldc           #40                 // String no
          32: invokevirtual #34                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          35: return        
    

    I therefore strongly suspect the == was part of the original source code.