JVM option to optimize loop statements

It depends on what foo.getLength() does. If it can be inlined, it can be effectively the same thing. If it cannot be inlined, the JVM cannot determine whether the result is the same.

BTW you can write for a one liner.

for(int i = 0, length = foo.getLength(); i < length; i++){   }

EDIT: It is worth nothing that;

  • methods and loops are usually not optimised until they have been called 10,000 times.
  • profilers sub-sample invocations to reduce overhead. They might count every 10 or 100 or more so a trivial example may not show up.

I've made some test in java and it seems that by default index and bound are recalculate each time.

According to the Java Language Specification, this:

for(int i = 0 ; i < foo.getLength() ; i++){   }

means that getLength() is called on each loop iteration. Java compilers are only allowed to move the getLength() call out of the loop if they can effectively prove that it does not alter the observable behavior.

(For instance, if getLength() just returns the value of some variable, then there is a chance that the JIT compiler can inline the call. If after inlining it can deduce that the variable won't change (under certain assumptions) it can apply a hoisting optimization. On the other hand, if getLength() involves getting the length of a concurrent or synchronized collection, the chances are slim to none that the hoisting optimization will be permitted ... because of potential actions of other threads.)

So that's what a compiler is allowed to do.

I'm wondering if it's possible to activate this kind of feature in the JVM HotSpot?

The simple answer is No.

You seem to be suggesting a compiler switch that tells / allows the compiler to ignore the JLS rules. There is no such switch. Such a switch would be a BAD IDEA. It would be liable to cause correct/valid/working programs to break. Consider this:

class Test {
   int count;

   int test(String[] arg) {
       for (int i = 0; i < getLength(arg); i++) {
           // ...
       }
       return count;
   }

   int getLength(String[] arg) {
       count++;
       return arg.length;
   }
}

If the compiler was permitted to move the getLength(arg) call out of the loop, it would change the number of times that the method was called, and therefore change the value returned by the test method.

Java optimizations that change the behaviour of a properly written Java program are not valid optimizations. (Note that multi-threading tends to muddy the waters. The JLS, and specifically the memory model rules, permit a compiler to perform optimizations that could result in different threads seeing inconsistent versions of the application's state ... if they don't synchronize properly, resulting in behaviour that is incorrect from the developer's perspective. But the real problem is with the application, not the compiler.)


By the way, a more convincing reason that you shouldn't change the loop variable in the loop body is that it makes your code harder to understand.


The main reason not to do that is that it makes it much harder to understand and maintain the code.

Whatever the JVM optimizes, it won't compromise the correctness of the program. If it can't do an optimization because the index is modified inside the loop, then it won't optimize it. I fail to see how a Java test could show if there is or not such an optimization.

Anyway, Hotspot will optimize a whole lot of things for you. And your second example is a kind of explicit optimization that Hotspot will happily do for you.