Java编译器优化

时间:2011-05-12 16:42:22

标签: java optimization javac

最近,我正在阅读article

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

6 个答案:

答案 0 :(得分:78)

javac只会进行一些优化,如果有的话。

关键是JIT编译器完成了大部分优化 - 如果它有大量信息,它会工作得最好,如果javac执行优化,其中一些信息可能会丢失。如果javac执行某种类型的循环展开,那么JIT通常会以一般方式执行此操作 - 并且它有更多关于哪些优化将实际工作的信息,因为它了解目标平台。

答案 1 :(得分:25)

当我到达本节时,我停止阅读:

  

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

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

答案 2 :(得分:14)

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

然而,启动J2SE1.3,the HotSpot JVM was shipped with the platform,它引入了动态技术,例如即时编译和公共执行路径的自适应优化。因此,启动此版本的Java编译器忽略了-o

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

  

指示是否应使用优化编译源;默认为off注意,从JDK 1.3开始,Sun {#1}}忽略了这个标志(因为编译时优化是不必要的)。

this page中提到了HotSpot JVM动态优化优于编译时优化的优势:

  

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

答案 3 :(得分:8)

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

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

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

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

答案 4 :(得分:1)

要优化字节码,您可以使用Proguard

正如其他人所说,主流JVM中的JIT会在编译代码时优化代码,并且可以访问更多上下文,它可能会超越Proguard。在更简单的VM中可能不是这种情况。在Android世界中,通常的做法是在针对Dalvik(在Lollipop之前附带Android的VM)中使用Proguard优化。

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

答案 5 :(得分:0)

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

如果您要针对的运行时类型没有JIT优化器(即使它具有JIT编译器),或者您是AOT编译,则建议使用Proguard或Allatori之类的优化混淆器。