Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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'?

like image 689
andy boot Avatar asked Apr 11 '13 20:04

andy boot


1 Answers

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.

like image 121
NPE Avatar answered Oct 20 '22 04:10

NPE