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

4

2 回答 2

3

要记住的一件事是javac(Java 源代码到字节码编译器)不是优化编译器。事实上,它的代码生成相对简单,并且只生成任何给定源代码的最直接的字节码实现。

这完全是设计使然。这样,负责所有实际优化的 JVM 拥有最大数量的可用信息,可作为其决策的基础。在这种特殊情况下,这些信息如何使 JIT 编译器受益可能并不明显,但由于 HotSpot 进行优化的性质,每一点信息都可以提供帮助。

例如,可能有一些智能模式匹配可以识别常见的代码片段并在高度优化的版本中实现它们。现在,如果javac也尝试进行一些优化,那么这些模式可能更难检测到。

于 2010-02-23T11:43:40.177 回答
2

Sun 的 Javac 本身没有做任何优化,因为它们留给了 HotSpot VM。因此它产生了第一个字节码。

第二个字节码列表与第一个一样有效。所以理论上一些其他的Java编译器可以产生这个。

如果没有 JIT 的 VM(例如 Android 设备)需要这种优化,可以使用 Proguard 等工具在字节码级别进行优化。

于 2010-02-23T11:41:50.250 回答