Java编译器的优化

Java编译器的优化,java,optimization,javac,Java,Optimization,Javac,最近,我在读这篇文章 根据那篇文章,Java编译器即javac在生成字节码时不执行任何优化。这是真的吗?如果是这样,那么它能否实现为一个中间代码生成器,以消除冗余并生成最佳代码?javac将只进行很少的优化(如果有的话) 关键是JIT编译器完成了大部分优化——如果它有很多信息,那么它的工作效果最好,如果javac也执行了优化,其中一些信息可能会丢失。如果javac执行了某种循环展开,JIT将更难以一般方式自行展开,而且它知道目标平台,因此它有更多关于哪些优化将实际起作用的信息。当我读到这一部分时

最近,我在读这篇文章


根据那篇文章,Java编译器即javac在生成字节码时不执行任何优化。这是真的吗?如果是这样,那么它能否实现为一个中间代码生成器,以消除冗余并生成最佳代码?

javac
将只进行很少的优化(如果有的话)


关键是JIT编译器完成了大部分优化——如果它有很多信息,那么它的工作效果最好,如果
javac
也执行了优化,其中一些信息可能会丢失。如果
javac
执行了某种循环展开,JIT将更难以一般方式自行展开,而且它知道目标平台,因此它有更多关于哪些优化将实际起作用的信息。

当我读到这一部分时,我停止了阅读:

更重要的是,javac编译器 不执行简单的优化 像循环展开,代数的 简化,强度降低, 等等。为了获得这些好处和 其他简单的优化 程序员必须在计算机上执行它们 Java源代码,不依赖 javac编译器来执行它们


首先,在Java源代码上进行循环展开从来都不是一个好主意。Java C在优化方面做得不多的原因是它是由JVM中的JIT编译器完成的,它可以做出编译器可以做出的更好的决定,因为它可以准确地看到哪些代码运行得最多。

我过去研究过输出的Java字节码(使用一个名为FrontEnd的应用程序)。它基本上不做任何优化,除了内联常量(静态韵母)和预计算固定表达式(如2*5和“ab”+“cd”)。这就是为什么is如此容易拆卸的部分原因(使用名为JAD的应用程序)

我还发现了一些优化java代码的有趣之处。它帮助我将内环的速度提高了2.5倍

一个方法有5个快速访问变量。调用这些变量时,它们比所有其他变量都快(可能是因为堆栈维护)。方法的参数也计算到这5个。因此,如果在for循环中有代码,并且执行了一百万次,那么在方法开始时分配这些变量,并且没有参数


局部变量也比字段快,因此,如果在内部循环中使用字段,请通过在方法开始时将这些变量分配给局部变量来缓存这些变量。缓存引用而不是内容。(比如:int[]px=this.pixels;)

javac编译器曾经支持通过在命令行上传递
-o
来生成优化字节码的选项

但是,从J2SE1.3开始,它引入了动态技术,例如即时编译和通用执行路径的自适应优化。因此,启动此版本的Java编译器忽略了
-o

我在阅读Ant任务及其
optimize
属性时遇到了这个标志:

指示是否应优化编译源代码;默认设置为关闭注意Sun的
javac
从JDK1.3开始忽略了这个标志(因为编译时优化是不必要的)

HotSpot JVM的动态优化优于编译时优化的优点如下所述:

服务器VM包含一个高级的自适应编译器,它支持通过优化C++编译器执行的许多相同类型的优化,以及一些传统编译器无法完成的优化,例如在虚拟方法调用中的积极内联。这是相对于静态编译器的竞争优势和性能优势。自适应优化技术在方法上非常灵活,通常甚至优于高级静态分析和编译技术


要优化字节码,可以使用

正如其他人所指出的,主流JVM中的JIT将在编译代码时优化代码。它的性能可能会优于Proguard,因为它可以访问更多的上下文。但在更简单的虚拟机中可能并非如此。在Android世界,当目标是Dalvik(在棒棒糖出现之前,Android附带的VM)时,使用Proguard优化是一种常见的做法


Proguard还收缩和模糊字节码,这是在运送客户端应用程序时必须的(即使您不使用优化)。

编译器不会优化字节码,因为它在运行时由JIT优化器优化


如果您所针对的运行时类型没有JIT优化器(即使它有JIT编译器),或者您正在进行AOT编译,我建议您使用Proguard或Allatori之类的优化模糊器。

不完全是重复的,但答案可能很有趣:嗯,这篇文章已经有十年历史了。这仍然是真的吗(我不知道哪种方式)?我建议您使用更现代的文档进行一些研究。常量表达式处理(包括最终变量-如果它们具有常量值,则不必是静态的)实际上是由语言规范规定的。您能否提供有关这些“5个快速访问变量”的更多信息?我知道字节码指令,但它们只有4条,从0到3(对于
astore\uu
也是如此)。我甚至不确定它们是否比正常的
aload
操作执行得更好(除了它们不需要额外的索引字节,所以需要一些安全的空间)。不过,我同意“局部变量vs.字段”的观点,-1传播了编译时优化是不可取的Java神话。有些编译过程可能非常昂贵,散布JIT应该负责完成所有工作的想法是毫无意义的。事实上,C和C++在优化时仍然比java做得更好。