Java字节码iconst_0 iadd序列

时间:2010-02-23 11:22:19

标签: java bytecode ternary-operator

以下是三元运算符的有趣测试:

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

这是生成的字节码:

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

我有点惊讶地发现它没有删除'+ 0'的'else'情况。我更期待这个:

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

所以这就是我的问题:规范是否要求:

goto ...
iconst_0

序列,因为我使用了三元运算符,或者这只是一个编译器的东西?

显然这个问题不是关于写'r + = ...的相关性? 1:0'。但我很惊讶,因为在其他情况下编译器会做一些优化,而在这里它没有进行任何优化。

生成选项2的Java编译器是否仍然是一个有效的Java编译器(如果我没有搞砸我的例子,但关键是:在编写的代码中有一个不必要的0和一个不必要的goto,编译器会不会删除它仍然是一个有效的.java编译器)?

2 个答案:

答案 0 :(得分:3)

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

这完全是设计上的。通过这种方式,负责所有实际优化的JVM具有可用于其决策的最大信息量。在这种特殊情况下,该信息如何使JIT编译器受益可能并不明显,但由于HotSpot优化的性质,例如,每一点信息都可以提供帮助。

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

答案 1 :(得分:2)

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

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

如果没有JIT的VM(例如Android设备)需要这种优化,那么像Proguard这样的工具会对字节码级别进行优化。