繁体   English   中英

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

[英]why doesn't the java compiler rewrite this code?

我正在测试这段代码:

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被编译为在堆栈上推送和弹出1个变量,而rightComparison推送和弹出2.我推测leftComparison因此比rightComparison稍微有效?

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

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

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

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

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

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

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


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

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

  1. 它引入了不必要的维护开销层。
  2. 当我们了解目标平台时,最好进行优化。 无论如何,基于Java堆栈的指令集不适合高级优化。 它太简单了(按设计)。 我们可以通过改变一些基于堆栈的操作码来实现这么多“优化”。 虽然在javac中进行大量高级“无脑”优化是可行的,但我认为实用主义在这里已经取得了成功,我们将其归功于JIT,它可以利用更丰富的本机构造和技术(不同通过平台)在字节码中不可用。

几乎是因为“这就是它的编写方式”。 比较考虑了左手变量并将其与右侧进行比较。 当你说null == s ,你会说“将null与这个变量进行比较”,所以代码定义了一个null的常量来比较。 编译器只是将其他比较优化为非空检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM