兼容的Java编译器能否优化此代码?

兼容的Java编译器能否优化此代码?,java,optimization,compiler-construction,javac,Java,Optimization,Compiler Construction,Javac,今天,我在教授一门编程入门课程,并且正在浏览一些涉及Java中变量赋值的简单代码。代码的重点不是要展示任何特别令人兴奋的东西,而是要确保学生理解变量赋值语句 我在黑板上找到了以下方法,并一行一行地追踪它: private void simpleMethod() { int myInt = 137; myInt = 42; myInt = myInt + 1; /* ... code using myInt ... */ } 一个学生问我,当程序运行时,myIn

今天,我在教授一门编程入门课程,并且正在浏览一些涉及Java中变量赋值的简单代码。代码的重点不是要展示任何特别令人兴奋的东西,而是要确保学生理解变量赋值语句

我在黑板上找到了以下方法,并一行一行地追踪它:

private void simpleMethod() {
    int myInt = 137;
    myInt = 42;
    myInt = myInt + 1;

    /* ... code using myInt ... */
}
一个学生问我,当程序运行时,
myInt
是否会实际保持137和42的值,或者它是否会直接跳到保持43。我告诉学生,代码将依次执行每一行,因此变量实际上将保存这些中间值

老实说,我不确定字节码
javac
会发出什么(完全忽略了JVM所做的优化)。法律是否允许
javac
(或任何Java编译器)优化愚蠢的赋值语句,而直接将
myInt
初始化为43

根据
javap
,在我的系统上,上面用
javac
编译的代码生成

   0: sipush        137
   3: istore_1      
   4: bipush        42
   6: istore_1      
   7: iload_1       
   8: iconst_1      
   9: iadd          
  10: istore_1      
  11: return        

所以这里没有进行优化。不过,我的问题是,优化它是否合法,所以这并不能解决任何问题。

我相信Java编译器可以执行任何常量折叠,它可以在编译时静态确定

是的,这可以通过
javac
来优化


然而,
javac
不需要进行这种优化,因为JVM-JIT编译器几乎肯定会为您做同样的优化。从这个角度来看,Java->Bytecode编译器是否进行了这种优化可能与对运行时执行的实际本机代码的影响无关。

JLS只指定了程序产生的可观察行为的契约。由于
myInt
是本地的,因此优化确实可以在编译时进行优化,因为这将产生与规范一致的行为,规范中没有任何内容表明不允许这样做(至少我没有发现!)。规范的定义明确规定了规范的可观察性:
本文档完全规定了表达式的(明显)求值顺序…
。由于表观行为通过不断折叠到
myInt=43
而保持不变,因此优化将与JLS一致

事实上,Java应用程序的编译目标甚至没有在JLS中指定。第1章说Java应用程序“通常”编译为JVM规范(一个单独的文档)中指定的字节码,但并不要求它们这样做。有一些必须在编译时优化,但是
myInt
不是这样的。即使
myInt
是一个字段,我认为优化是允许的;不同的行为仍然是有效的行为,即使
myInt
是易变的(因为它代表一个有效的事件顺序)

所以,简短的回答,我认为你的学生是正确的;将其优化为仅
myInt=43
是非常好的。也就是说,
javac
在优化方面通常做得很少,实际上什么都没有。优化几乎都是在JIT中完成的

所以这里没有进行优化

考虑到Java使用动态编译,这应该不会太令人惊讶

JVM在运行时优化了几乎所有的代码,这意味着无论您使用1996年为Java 1.0编译的代码还是Scala或JRuby、JGo等,您都可以充分利用对特定CPU型号的本机代码的优化

因此,许多语言都有JVM实现,因此它们不需要为JVM运行的所有平台生成最佳代码


虽然这是事实,但我的问题是编译器是否合法 允许进行此优化

通过传统的数据流分析(流/传递函数、输入集、输出集、发电集、压井集等),特别是一些路径,向前推进数据流,即达到定义(或使用def链)。。。对本质上,优化器可以将变量的每次使用链接到到达它的定义

在这种情况下,优化器可以确定myInt(=137)的初始定义从未达到其用途,而另一个定义(=42 1)确实达到其用途,因为它从未在从该定义到其用途的任何(某些)路径上重新定义

参考资料:

  • 龙书1ed(1986)第10章
  • 龙书2ed(2007)第9章(具体为9.2)

1-我在教学代码中一直使用42。我敢打赌我们都是这样。

我想你可以很容易地用
javap
测试任务是否优化。无论是否合法,都要优化这个。。。这也是我想知道的。@nhahtdh-Output from
javap
如上所示。没有进行优化。唯一可以在编译时进行优化的安全情况可能是局部变量。如果代码涉及实例或类成员,编译时优化可能会导致意外行为。您能找到支持此操作的引用吗?我很抱歉,如果这似乎是一个不寻常的要求,但我一直在想这类问题一段时间,并希望有一个明确的答案,如果可能的话。我正在寻找一个在JLS的参考。但似乎找不到。也许这是一个与JLS不矛盾的情况……虽然这是真的,但我的问题是编译器是否合法地被允许进行优化,而不是它是否是一个好主意或进行优化的正确位置。不过,谢谢@templatetypedef考虑到过去16年的编译器设计是为了使其在优化方面尽可能简单,我相信这不是
javac
所能做到的。公司