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

Jam*_*mes 5 java compiler-construction compiler-optimization

我正在测试这段代码:

public class TestNull {
   public void leftComparison(String s) {
       if (s == null);
   }
   public void rightComparison(String s) {
       if (null == s);
   }
}
Run Code Online (Sandbox Code Playgroud)

我用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        
}
Run Code Online (Sandbox Code Playgroud)

显然,leftComparison编译是在推送和弹出2时在堆栈上推送和弹出1个变量rightComparison.我推测这样的leftComparison效率会稍微高于rightComparison

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

Ste*_*n C 5

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

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

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

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

在我看来,这两个比较应该在语义上是等价的,对吧?

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


这里真正的教训是,字节码编译器生成的字节码序列几乎不会告诉您代码实际执行的方式.您可能从读取字节码中得出的任何性能结论都是非常可疑的.