兼容的Java编译器可以优化此代码吗?

tem*_*def 16 java compiler-construction optimization javac

我今天正在教授一门入门编程课程,并且正在介绍一些涉及Java中变量赋值的简单代码.代码的要点不是炫耀任何特别令人兴奋的东西,而是主要是为了确保学生理解变量赋值语句.

我在电路板上有以下方法,并且一次只追踪一行:

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

    /* ... code using myInt ... */
}
Run Code Online (Sandbox Code Playgroud)

一个学生问我是否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        
Run Code Online (Sandbox Code Playgroud)

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

ysh*_*vit 8

JLS仅指定程序生成的可观察行为的合约.由于myInt是本地的,优化确实可以在编译时进行优化,因为这会产生与规范一致的行为,并且规范中没有任何内容表明它是不允许的(至少,不是我发现的!).规范的第1章明确规定了规范的可观察性:This document fully specifies the (apparent) order of evaluation of expressions....由于通过常量折叠来改变表观行为myInt = 43,因此优化将与JLS一致.

实际上,甚至在JLS中都没有指定Java应用程序的编译目标.第1章说Java应用程序"通常"编译为JVM规范中指定的字节码(单独的文档),但并不要求它们这样做.还有一些语句必须在编译时进行优化,但myInt不是这样的.即使myInt是一个领域,我认为优化是允许的; 不同的行为仍然是有效的行为,即使myInt是不稳定的(因为它代表了一个有效的事件排序).

所以,简短的回答,我认为你的学生是正确的; 将它优化到最佳状态是完美的myInt = 43.也就是说,javac通常在优化方面做的很少 - 几乎没有.优化几乎都在JIT中完成.


mik*_*era 5

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

所以,是的,这可以通过优化javac.

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