Java编译器优化

最近,我正在阅读这篇文章 。

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

如果有的话, javac只会做很less的优化。

关键是JIT编译器会进行大部分的优化 – 如果它有大量的信息,最好的方法就是最好,如果javac执行优化的话,其中一些信息可能会丢失。 如果javac执行某种types的循环展开,那么JIT就会以一般的方式自己完成这个操作 – 而且它知道哪些优化实际上可以工作,因为它知道目标平台。

当我到达这个部分时,我停止阅读:

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

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

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

然而,启动J2SE1.3后, HotSpot JVM随平台一起发布 ,引入了即时编译和自适应优化等常用执行path等dynamic技术。 因此,Java编译器开始这个版本时忽略了-o

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

指示源是否应优化编译; 默认off请注意 ,Sun的javac从JDK 1.3开始就忽略了这个标志(因为不需要编译时优化)。

本页提到了HotSpot JVMdynamic优化优化编译时优化的优点:

Server VM包含一个高级自适应编译器,支持通过优化C ++编译器执行的许多相同types的优化,以及传统编译器无法完成的一些优化,例如跨虚拟方法调用的积极内联。 与静态编译器相比,这是一个有竞争力的性能优势。 自适应优化技术在其方法中是非常灵活的,并且典型地甚至比先进的静态分析和编译技术更胜一筹。

我已经研究过输出的Java字节码(使用名为FrontEnd的应用程序)。 除了内联常量(静态总决赛)和预先计算的固定expression式(如2 * 5和“ab”+“cd”)外,基本上不做任何优化。 这是为什么很容易反汇编(使用称为JAD的应用程序)的一部分,

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

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

局部variables也比字段更快,所以如果你在内部循环中使用字段,通过在方法开始时把这些variables赋值给局部variables来caching这些variables。 caching参考而不是内容。 (如:int [] px = this.pixels;)

为了优化你的字节码,你可以使用Proguard 。

正如其他人所指出的那样,主streamJVM中的JIT会在编译代码时优化代码,并且由于它可以访问更多的上下文,所以它可能会比Proguard更胜一筹。 更简单的虚拟机可能不是这种情况。 在Android世界中,当针对Dalvik(在Lollipop之前与Android一起提供的VM)时,通常会使用Proguard优化。

Proguard还会缩小和混淆字节码,这在发送客户端应用程序时是必须的(即使您不使用优化)。