【问题标题】:Java bytecode iconst_0 iadd sequenceJava字节码iconst_0 iadd序列
【发布时间】:2011-01-20 00:43:59
【问题描述】:

这是一个有趣的三元运算符测试:

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

sequence 因为我使用了三元运算符,或者这只是编译器的事情?

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

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

【问题讨论】:

    标签: java bytecode ternary-operator


    【解决方案1】:

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

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

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

    【讨论】:

    • @Lauri:Proguard 已集成在我们的构建过程中,所以我会出于好奇而研究它
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-15
      • 2013-08-04
      相关资源
      最近更新 更多