Will the Java compiler optimize String.length () in loop conditions?

Consider the following Java code snippet:

String buffer = "..."; for (int i = 0; i < buffer.length(); i++) { System.out.println(buffer.charAt(i)); } 

Since String immutable and buffer not reassigned in the loop, will the Java compiler be smart enough to optimize the call to buffer.length() in the loop loop condition? For example, will it produce a bytecode equivalent to the following, where buffer.length() is assigned to a variable, and this variable is used in a loop condition? I read that some languages, such as C #, do this type of optimization.

 String buffer = "..."; int length = buffer.length(); for (int i = 0; i < length; i++) { System.out.println(buffer.charAt(i)); } 
+7
java
source share
3 answers

In Java (and in .Net), strings are counted by length (the number of UTF-16 code points), so finding a length is a simple operation.

The compiler ( javac ) may or may not perform hoisting , but the JVM JIT compiler will almost certainly include the .length() call, making buffer.length() nothing more than memory access.

+6
source share

The Java compiler ( javac ) does not perform such an optimization. The JIT compiler will most likely build a length() method, which at least avoids the overhead of invoking the method.

Depending on which JDK you are using, the length() method will most likely return a final field of length , which is cheap memory access or the length of the char[] internal array. In the latter case, the length of the array is constant, and the reference to the array is supposedly final , so the JIT can be complex enough to write the length once in the temporary, as you suggest. However, such a thing is an implementation detail. Unless you control every machine your code runs on, you should not make too many assumptions about which JVM it will run or which optimizations it will perform.

As for how you should write your code, calling length() directly in the loop condition is a general code template and allows you to read. I would keep it simple and let the JIT optimizer do its job if you don’t have critical code that showed performance problems and you also showed that such micro-optimization is worth it.

+1
source share

You can do several things to explore two options for your implementation.

  • (difficulty: easy) Take a test and measure the speed under similar conditions for each version of the code. Make sure the loop is large enough to notice the difference, it is possible that it is not there.

  • (difficulty: medium) Examine the bytecode using javap and see how the compiler interpreted both versions (this may vary depending on the javac implementation), or it may not be so (when the behavior was specified in the specification and there was no room for interpretation by the developer).

  • (difficulty: hard). Examine the JIT output of both versions with JITWatch, you will need to understand the bytecode and assembler very well.

+1
source share

All Articles