views:

205

answers:

2

Here's a test for fun with the ternary operator:

public int so( final int a ) {
    int r = (int) System.currentTimeMillis();
    r += a == 2 ? 1 : 0;
    return r;
}

Here's the bytecode produced:

public int doIt(int);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   l2i
   4:   istore_2
   5:   iload_2
   6:   iload_1
   7:   iconst_2
   8:   if_icmpne       15
   11:  iconst_1
   12:  goto    16
   15:  iconst_0
   16:  iadd
   17:  istore_2
   18:  iload_2
   19:  ireturn

I was a bit surprised to see that it didn't remove the 'else' case for the '+ 0'. I was more expecting this:

public int doIt(int);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   l2i
   4:   istore_2
   5:   iload_1
   6:   iconst_2
   7:   if_icmpne       13
   10:  iinc    2, 1
   13:  iload_2
   14:  ireturn

So here comes my question: does the specs mandates the:

goto ...
iconst_0

sequence because I used the ternary operator, or is this just a compiler thinggy?

Obviously this question is not about the relevancy of writing 'r += ... ? 1 : 0'. But I'm surprised because in other cases the compiler does quite some optimization while here it's not doing any optimization.

Would a Java compiler producing option 2 still be a valid Java compiler (in case I didn't screw my example, but the point is: there's a needless addition of 0 and a needless goto in the code produced, would a compiler removing this still be a valid .java compiler)?

+2  A: 

Sun's Javac itself does not do any optimizations as they are left for the HotSpot VM. Thus it produces the first bytecode.

The second bytecode listing is as valid as the first one. So in theory some other Java compiler could produce that.

If that kind of optimizations are needed for VMs that does not have JIT (for example Android devices), there are tools like Proguard that do optimizations on bytecode level.

Lauri
@Lauri: Proguard is integrated in our build process so I shall look into it out of curiosity
Webinator
+2  A: 

One thing to keep in mind is that javac (the Java Source code to byte code compiler) is not an optimizing compiler. In fact it is relatively simple in its code generation and only produces the most straight-forward byte-code implementation of any given source code.

That is entirely by design. This way the JVM, which is in charge of all the real optimizations, has the maximum amount of information available on which to base its decisions. In this particular case it might not be obvious how that information can benefit the JIT compiler, but due to the nature of optimizations done by HotSpot for example, every bit of information can help.

For example there might be some smart pattern matching that recognizes common pieces of code and implements them in a highly optimized version. Now if javac tried to do some optimization as well, then those patterns could be much harder to detect.

Joachim Sauer