Created: 10/9/96 PatrickB

Return to the Java Hall of Shame

Javac Misoptimizing "Constant" if statements

javac can incorrectly optimize away calls to routines with side effects. Sun's Java compiler sometimes optimizes away if statements when the compiler thinks that the condition will always evaluate to true. javac fails to take into account the fact that subroutines called during evaluation of the conditional may have side effects such as throwing exceptions or assigning to class variables, and will optimize them away. For example:
class test {
    static int p = 0;
    static int foo(int a) throws Exception {
        if (a < 0) {
	    p = 1;
	    throw new Exception();
	}
	return 1;
    }

  
    static void test1(int a) throws Exception  {
        int j;

        j = 0;
	if (foo(a) < 0 || true) {
            j = 1;
	}
    }
    static public void main(String argv[]) throws Exception {
        test1(-1);
        System.out.println(p);
    }
}
This program should always throw an exception back to the top level and print nothing. What happens when we run it?
> javac -O test.java
> java test
0
No exception was thrown back to the top level, and p wasn't changed! By looking at the disassembly, you can see that javac (incorrectly) optimized away the call to foo().
> javap -c test
Compiled from test.java
class test extends java.lang.Object {
    static int p;
    static int foo(int);
    static void test1(int);
    public static void main(java.lang.String []);
    test();

Method int foo(int)
   0 iload_0
   1 ifge 16
   4 iconst_1
   5 putstatic #7 
   8 new #2 
  11 dup
  12 invokenonvirtual #9 ()V>
  15 athrow
  16 iconst_1
  17 ireturn

Method void test1(int)
   0 iconst_0
   1 istore_1
   2 iconst_1
   3 istore_1
   4 getstatic #10 
   7 getstatic #7 
  10 invokevirtual #6 
  13 return

Method void main(java.lang.String [])
   0 iconst_m1
   1 invokestatic #8 
   4 return

Method test()
   0 aload_0
   1 invokenonvirtual #11 ()V>
   4 return

}
 
Return to the Java Hall of Shame