我今天教了一门入门编程课程,正在学习一些简单的代码,其中涉及到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 所以这里没有优化。不过,我的问题是,优化它是否合法,所以这不能解决任何问题。
发布于 2013-01-15 07:59:57
JLS只指定程序产生的可观察行为的契约。由于myInt是本地的,所以可以在编译时对优化进行优化,因为这将产生与规范一致的行为,而且规范中没有任何内容表示不允许使用它(至少,我没有发现!)规范的第一章显式地指定规范的可观察性:This document fully specifies the (apparent) order of evaluation of expressions...。由于通过常量折叠到myInt = 43,表观行为不变,因此优化将与JLS一致。
实际上,JLS中甚至没有指定Java应用程序的编译目标。第一章说Java应用程序“通常”编译到JVM规范中指定的字节码(一个单独的文档),但它并不要求它们这样做。有些一些陈述必须在编译时进行优化,但myInt并不是其中之一。即使myInt是一个字段,我也认为优化是允许的;不同的行为仍然是有效的行为,即使myInt是不稳定的(因为它代表了一个有效的事件排序)。
因此,简单的回答,我认为你的学生是正确的;它是完全好的优化它只是myInt = 43。也就是说,javac在优化方面通常做得很少--实际上什么也没有做。优化几乎都是在JIT中完成的。
发布于 2013-01-15 07:06:14
我相信Java编译器可以在编译时进行静态确定的任何常量折叠。
因此,是的,javac可以对此进行优化。
但是,javac不需要进行这种优化,因为JIT编译器几乎肯定会为您做同样的优化。从这个角度来看,JavaJava字节码编译器是否进行这种优化可能与对运行时执行的实际本机代码的影响无关。
发布于 2013-01-15 08:09:31
所以这里没有优化。
这并不奇怪,因为Java使用动态编译。
JVM在运行时对几乎所有的代码进行了优化,这意味着无论您是使用1996年为Java1.0编译的代码,还是使用Scala或JRuby、JGo等,您都可以从优化特定CPU模型的本机代码中获得全部好处。
因此,许多语言都有JVM实现,因此它们不需要为JVM运行的所有平台生成最佳代码。
https://stackoverflow.com/questions/14332577
复制相似问题