Java 编译器优化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5981460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 13:50:03  来源:igfitidea点击:

Optimization by Java Compiler

javaoptimizationjavac

提问by Mahesh Gupta

Recently, I was reading this article.

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

According to that article, Java Compiler i.e. javac does not perform any optimization while generating bytecode. Is it really true? If so, then can it be implemented as an intermediate code generator to remove redundancy and generate optimal code?

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

回答by Jon Skeet

javacwill only do a very little optimization, if any.

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

The point is that the JIT compiler does most of the optimization - and it works best if it has a lot of information, some of which may be lost if javacperformed optimization too. If javacperformed some sort of loop unrolling, it would be harder for the JIT to do that itself in a general way - and it has more information about which optimizations will actuallywork, as it knows the target platform.

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

回答by Simon Nickerson

I stopped reading when I got to this section:

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

More importantly, the javac compiler does not perform simple optimizations like loop unrolling, algebraic simplification, strength reduction, and others. To get these benefits and other simple optimizations, the programmer must perform them on the Java source code and not rely on the javac compiler to perform them.

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

Firstly, doing loop unrolling on Java source code is hardly ever a good idea. The reason javacdoesn't do much in the way of optimization is that it's done by the JIT compiler in the JVM, which can make much better decisions that the compiler could, because it can see exactly which code is getting run the most.

首先,对 Java 源代码进行循环展开几乎不是一个好主意。之所以javac没有做太多优化,是因为它是由 JVM 中的 JIT 编译器完成的,它可以做出比编译器更好的决策,因为它可以准确地看到哪些代码运行得最多。

回答by M Anouti

The javaccompiler once supported an option to generate optimized bytecode by passing -oon the command line.

所述javac编译器一次支持的选项,通过传递来生成优化代码-o在命令行上。

However starting J2SE1.3, the HotSpot JVM was shipped with the platform, which introduced dynamic techniques such as just-in-time compilation and adaptive optimization of common execution paths. Hence the -owas ignored by the Java compiler starting this version.

但是从 J2SE1.3 开始,HotSpot JVM 随平台一起提供,它引入了动态技术,例如即时编译和常见执行路径的自适应优化。因此,-o从这个版本开始的 Java 编译器忽略了 。

I came across this flag when reading about the Ant javactask and its optimizeattribute:

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

Indicates whether source should be compiled with optimization; defaults to off. Notethat this flag is just ignored by Sun's javacstarting with JDK 1.3 (since compile-time optimization is unnecessary).

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

The advantages of the HotSpot JVM's dynamic optimizations over compile-time optimization are mentioned in this page:

本页提到了 HotSpot JVM 的动态优化相对于编译时优化的优势:

The Server VM contains an advanced adaptive compiler that supports many of the same types of optimizations performed by optimizing C++ compilers, as well as some optimizations that cannot be done by traditional compilers, such as aggressive inlining across virtual method invocations. This is a competitive and performance advantage over static compilers. Adaptive optimization technology is very flexible in its approach, and typically outperforms even advanced static analysis and compilation techniques.

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

回答by Zom-B

I have studied outputted Java bytecode in the past (using an app called FrontEnd). It basically doesn't do any optimization, except for inlining constants (static finals) and precalculating fixed expressions (like 2*5 and "ab"+"cd"). This is part of why is is so easy to disassemble (using an app called JAD)

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

I also discovered some interesting points to optimize your java code with. It helped me improve speeds of inner-loops by 2.5 times.

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

A method has 5 quick-access variables. When these variables are called, they're faster than all other variables (probably because of stack maintainance). The parameters of a method are also counted to these 5. So if you have code inside for loop which is executed like a million times, allocate those variables at the start of the method, and have no parameters.

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

Local variables are also faster than fields, so if you use fields inside inner loops, cache these variables by assigning them to a local variable at the start of the method. Cache the reference not the contents. (like: int[] px = this.pixels;)

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

回答by Samuel Peter

To optimize your bytecode, you can use Proguard.

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

As others have noted, the JIT in a mainstream JVM will optimize the code while compiling it. It will probably outperform Proguard, because it has access to more context. But ths may not be the case in more simple VMs. In the Android world it is common practice to use Proguard optimizations when targeting Dalvik (the VM that came with Android before Lollipop).

正如其他人所指出的,主流 JVM 中的 JIT 将在编译时优化代码。它可能会胜过 Proguard,因为它可以访问更多上下文。但在更简单的 VM 中可能并非如此。在 Android 世界中,在针对 Dalvik(Lollipop 之前 Android 附带的 VM)时使用 Proguard 优化是常见的做法。

Proguard also shrinks and obfuscates the bytecode, which is a must when shipping client side applications (even if you don't use the optimizations).

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

回答by Jessie Lesbian

The compiler don't optimize the bytecode because it is optimized at run time by the JIT optimizer.

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

If the type of runtime you are targeting don't have a JIT optimizer (even if it had a JIT compiler), or you are AOT compiling, I recommend using an optimizing obfuscator like Proguard or Allatori.

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