最近,我正在阅读article。
根据那篇文章,Java Compiler即javac在生成字节码时不执行任何优化。这是真的吗?如果是这样,那么它可以作为中间代码生成器实现,以消除冗余并生成最佳代码吗?
答案 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之类的优化混淆器。