为什么java编译器没有重写这段代码?

时间:2014-07-23 02:54:46

标签: java compiler-construction compiler-optimization

我正在使用此代码进行测试:

public class TestNull {
   public void leftComparison(String s) {
       if (s == null);
   }
   public void rightComparison(String s) {
       if (null == s);
   }
}

我用javac 1.8.0_05编译它,然后检查了字节码:

public class TestNull {
  ....
  public void leftComparison(java.lang.String);
    Code:
       0: aload_1       
       1: ifnonnull     4
       4: return        

  public void rightComparison(java.lang.String);
     Code:
       0: aconst_null   
       1: aload_1       
       2: if_acmpne     5
       5: return        
}

显然,leftComparison被编译为在rightComparison推送和弹出2时在堆栈上推送和弹出1个变量。我推测leftComparison因此比rightComparison略高效}?

我想知道编译器为什么不重写rightComparison的代码?在我看来,这两个比较应该在语义上是等价的,对吧?

3 个答案:

答案 0 :(得分:5)

Java字节码编译器在优化方面做得很少。严重的优化工作几乎全部由JIT编译器完成。

  

我想知道编译器为什么不重写rightComparison的代码?

因为重写它没有意义。 JIT编译器应该能够处理它们,并且很可能为这两个版本生成最佳(本机)代码。 (如果您感兴趣,可以检查一下。有方法可以查看JIT编译器生成的本机代码。)

(另请参阅@ codenheim&#39的答案以获得更多技术解释。)

  

在我看来,这两个比较应该在语义上等同,对吗?

这是正确的......但它并不意味着字节码编译器有义务为两个版本生成相同的字节码序列。


这里的真正的课程是字节码编译器生成的字节码序列告诉您很少关于代码实际执行的方式。您从阅读字节码中得出的任何性能结论都是高度怀疑

答案 1 :(得分:2)

实际上,字节码相当于中间代码。过早优化或优化两次的投资回报率很低。

  1. 它引入了不必要的维护开销层。
  2. 当我们了解目标平台时,最好进行优化。无论如何,基于Java堆栈的指令集本身并不适合高级优化。它太简单了(按设计)。只有这么多"优化"我们可以通过改变一些基于堆栈的操作码来完成。尽管做很多高水平的人是可行的,但没有脑子能够做到这一点。在javac中进行优化,我认为实用主义在这里已经取得了成功,我们将它推向了JIT,它可以利用更丰富的本机指令集和技术(因平台而异),这些技术在字节码中是不可用的。

答案 2 :(得分:1)

几乎是因为"它是如何写的"。比较考虑了左手变量并将其与右侧进行比较。当您说null == s时,您说'#34;将null与此变量进行比较"所以代码定义了一个常量null来比较。编译器只是将其他比较优化为非空检查。