Optimization by Java Compiler

JavaOptimizationJavac

Java Problem Overview


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 Solutions


Solution 1 - Java

javac will only do a very little optimization, if any.

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 javac performed optimization too. If javac performed 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 actually work, as it knows the target platform.

Solution 2 - Java

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.

Firstly, doing loop unrolling on Java source code is hardly ever a good idea. The reason javac doesn'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.

Solution 3 - Java

The javac compiler once supported an option to generate optimized bytecode by passing -o on the command line.

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 -o was ignored by the Java compiler starting this version.

I came across this flag when reading about the Ant javac task and its optimize attribute:

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

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

>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.

Solution 4 - Java

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)

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

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.

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;)

Solution 5 - Java

To optimize your bytecode, you can use 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).

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

Solution 6 - Java

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

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMahesh GuptaView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaSimon NickersonView Answer on Stackoverflow
Solution 3 - JavaM AView Answer on Stackoverflow
Solution 4 - JavaZom-BView Answer on Stackoverflow
Solution 5 - JavaSamuel PeterView Answer on Stackoverflow
Solution 6 - JavaJessie LesbianView Answer on Stackoverflow