Does use of final keyword in Java improve the performance?

JavaPerformanceFinal

Java Problem Overview


In Java we see lots of places where the final keyword can be used but its use is uncommon.

For example:

String str = "abc";
System.out.println(str);

In the above case, str can be final but this is commonly left off.

When a method is never going to be overridden we can use final keyword. Similarly in case of a class which is not going to be inherited.

Does the use of final keyword in any or all of these cases really improve performance? If so, then how? Please explain. If the proper use of final really matters for performance, what habits should a Java programmer develop to make best use of the keyword?

Java Solutions


Solution 1 - Java

Usually not. For virtual methods, HotSpot keeps track of whether the method has actually been overridden, and is able to perform optimizations such as inlining on the assumption that a method hasn't been overridden - until it loads a class which overrides the method, at which point it can undo (or partially undo) those optimizations.

(Of course, this is assuming you're using HotSpot - but it's by far the most common JVM, so...)

To my mind you should use final based on clear design and readability rather than for performance reasons. If you want to change anything for performance reasons, you should perform appropriate measurements before bending the clearest code out of shape - that way you can decide whether any extra performance achieved is worth the poorer readability/design. (In my experience it's almost never worth it; YMMV.)

EDIT: As final fields have been mentioned, it's worth bringing up that they are often a good idea anyway, in terms of clear design. They also change the guaranteed behaviour in terms of cross-thread visibility: after a constructor has completed, any final fields are guaranteed to be visible in other threads immediately. This is probably the most common use of final in my experience, although as a supporter of Josh Bloch's "design for inheritance or prohibit it" rule of thumb, I should probably use final more often for classes...

Solution 2 - Java

Short answer: don't worry about it!

Long answer:

When talking about final local variables keep in mind that using the keyword final will help the compiler optimize the code statically, which may in the end result in faster code. For example, the final Strings a + b in the example below are concatenated statically (at compile time).

public class FinalTest {

	public static final int N_ITERATIONS = 1000000;

	public static String testFinal() {
		final String a = "a";
		final String b = "b";
		return a + b;
	}

	public static String testNonFinal() {
		String a = "a";
		String b = "b";
		return a + b;
	}

	public static void main(String[] args) {
		long tStart, tElapsed;

		tStart = System.currentTimeMillis();
		for (int i = 0; i < N_ITERATIONS; i++)
			testFinal();
		tElapsed = System.currentTimeMillis() - tStart;
		System.out.println("Method with finals took " + tElapsed + " ms");

		tStart = System.currentTimeMillis();
		for (int i = 0; i < N_ITERATIONS; i++)
			testNonFinal();
		tElapsed = System.currentTimeMillis() - tStart;
		System.out.println("Method without finals took " + tElapsed + " ms");

	}

}

The result?

Method with finals took 5 ms
Method without finals took 273 ms

Tested on Java Hotspot VM 1.7.0_45-b18.

So how much is the actual performance improvement? I don't dare say. In most cases probably marginal (~270 nanoseconds in this synthetic test because the string concatenation is avoided altogether - a rare case), but in highly optimized utility code it might be a factor. In any case the answer to the original question is yes, it might improve performance, but marginally at best.

Compile-time benefits aside, I could not find any evidence that the use of the keyword final has any measurable effect on performance.

Solution 3 - Java

YES it can. Here is an instance where final can boost performance:

Conditional compilation is a technique in which lines of code are not compiled into the class file based on a particular condition. This can be used to remove tons of debugging code in a production build.

consider the following:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (doSomething) {
       // do first part. 
    }

    if (doSomething) {
     // do second part. 
    }

    if (doSomething) {     
      // do third part. 
    }

    if (doSomething) {
    // do finalization part. 
    }
}

By converting the doSomething attribute into a final attribute, you have told the compiler that whenever it sees doSomething, it should replace it with false as per the compile-time substitution rules. The first pass of the compiler changes the code to something like this:

public class ConditionalCompile {

  private final static boolean doSomething= false;

    if (false){
       // do first part. 
    }

    if (false){
     // do second part. 
    }
 
    if (false){
      // do third part. 
    }
   
    if (false){
    // do finalization part. 

    }
}

Once this is done, the compiler takes another look at it and sees that there are unreachable statements in the code. Since you are working with a top-quality compiler, it doesn't like all those unreachable byte codes. So it removes them, and you end up with this:

public class ConditionalCompile {


  private final static boolean doSomething= false;

  public static void someMethodBetter( ) {

    // do first part. 

    // do second part. 

    // do third part. 

    // do finalization part. 

  }
}

thus reducing any excessive codes, or any unnecessary conditional checking.

Edit: As an example, let's take the following code:

public class Test {
	public static final void main(String[] args) {
		boolean x = false;
		if (x) {
			System.out.println("x");
		}
		final boolean y = false;
		if (y) {
			System.out.println("y");
		}
		if (false) {
			System.out.println("z");
		}
	}
}

When compiling this code with Java 8 and decompiling with javap -c Test.class we get:

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static final void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: ifeq          14
       6: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #22                 // String x
      11: invokevirtual #24                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: iconst_0
      15: istore_2
      16: return
}

We can note that compiled code includes only the non-final variable x. This prooves that final variables have impact on performances, at least for this simple case.

Solution 4 - Java

According to IBM - it doesnt for classes or methods.

http://www.ibm.com/developerworks/java/library/j-jtp04223.html

Solution 5 - Java

I am amazed that no one has actually posted some real code that is de-compiled to prove that there is at least some minor difference.

For the reference this has been tested against javac version 8, 9 and 10.

Suppose this method:

public static int test() {
    /* final */ Object left = new Object();
    Object right = new Object();

    return left.hashCode() + right.hashCode();
}

Compiling this code as it is, produces the exact same byte code as when final would have been present (final Object left = new Object();).

But this one:

public static int test() {
    /* final */ int left = 11;
    int right = 12;
    return left + right;
}

Produces:

   0: bipush        11
   2: istore_0
   3: bipush        12
   5: istore_1
   6: iload_0
   7: iload_1
   8: iadd
   9: ireturn

Leaving final to be present produces:

   0: bipush        12
   2: istore_1
   3: bipush        11
   5: iload_1
   6: iadd
   7: ireturn

The code is pretty much self-explanatory, in case there is a compile time constant, it will be loaded directly onto the operand stack (it will not be stored into local variables array like the previous example does via bipush 12; istore_0; iload_0) - which sort of makes sense since no one can change it.

On the other hand why in the second case the compiler does not produce istore_0 ... iload_0 is beyond me, it's not like that slot 0 is used in any way (it could shrink the variables array this way, but may be Im missing some internals details, can't tell for sure)

I was surprised to see such an optimization, considering how little ones javac does. As to should we always use final? I'm not even going to write a JMH test (which I wanted to initially), I am sure that the diff is in the order of ns (if possible to be captured at all). The only place this could be a problem, is when a method could not be inlined because of it's size (and declaring final would shrink that size by a few bytes).

There are two more finals that need to be addressed. First is when a method is final (from a JIT perspective), such a method is monomorphic - and these are the most beloved ones by the JVM.

Then there are final instance variables (that must be set in every constructor); these are important as they will guarantee a correctly published reference, as touched a bit here and also specified exactly by the JLS.


That being said : there is one more thing that is invisible to every single answer here: garbage collection. It is going to take a lot of time to explain, but when you read a variable, a GC has a so-called barrier for that read. Every aload and getField is "protected" via such a barrier, a lot more details here. In theory, final fields do not need such a "protection" (they can skip the barrier entirely). So if a GC does that - final will improve performance.

Solution 6 - Java

You are really asking about two (at least) different cases:

  1. final for local variables
  2. final for methods/classes

Jon Skeet has already answered 2). About 1):

I don't think it makes a difference; for local variables, the compiler can deduce whether the variable is final or not (simply by checking whether it is assigned more than once). So if the compiler wanted to optimize variables that are only assigned once, it can do so no matter whether the variable is actually declared final or not.

final might make a difference for protected/public class fields; there it's very difficult for the compiler to find out if the field is being set more than once, as it could happen from a different class (which may not even have been loaded). But even then the JVM could use the technique Jon describes (optimize optimistically, revert if a class is loaded which does change the field).

In summary, I don't see any reason why it should help performance. So this kind of micro-optimization is unlikely to help. You could try benchmarking it to make sure, but I doubt it will make a difference.

Edit:

Actually, according to Timo Westkämper's answer, final can improve performance for class fields in some cases. I stand corrected.

Solution 7 - Java

Note: Not a java expert

If I remember my java correctly, there would be very little way to improve performance using the final keyword. I've always known it to exist for "good code" - design and readability.

Solution 8 - Java

Final (At least for member variables and parameters) is more for humans then it is for the machine.

It's good practice to make variables final wherever possible. I wish Java had made "variables" final by default and had a "Mutable" keyword to allow changes. Immutable classes lead to much better threaded code, and just glancing at a class with "final" in front of each member will quickly show it to be immutable.

Another case--I've been converting a lot of code to use @NonNull/@Nullable annotations (You can say a method parameter must not be null then the IDE can warn you every place you pass a variable that isn't tagged @NonNull--the whole thing spreads to a ridiculous degree). It's much easier to prove a member variable or parameter can't be null when it's tagged final since you know it's not being re-assigned anywhere else.

My suggestion is to get in the habit of applying final for members and parameters by default, It's just a few characters but will nudge you towards improving your coding style if nothing else.

Final for methods or classes is another concept since it disallows a very valid form of reuse and doesn't really tell the reader much. The best use is probably the way they made String and the other intrinsic types final so you could rely on consistent behavior everywhere--That prevented a lot of bugs (although there are times I would have LOVED to extend string.... oh the possibilities)

Solution 9 - Java

As mentioned elsewhere, 'final' for a local variable, and to a slightly lesser extent a member variable, is more a matter of style.

'final' is a statement that you intend the variable to not change (i.e., the variable won't vary!). The compiler can then help you out by complaining if you violate your own constraint.

I share the sentiment that Java would have been a better language if identifiers (I'm sorry, I just cannot call a non-varying thing a 'variable') were final by default, and required you to explicitly say that they were variables. But having said that, I don't generally use 'final' on local variables that are initialized and never assigned; it just seems too noisy.

(I do use final on member variables)

Solution 10 - Java

I'm not an expert but I suppose you should add final keyword to the class or method if it won't be overwritten and leave variables alone. If there will be any way to optimize such things the compiler will do that for you.

Solution 11 - Java

Actually, while testing some OpenGL-related code, I found that using the final modifier on a private field can degrade performance. Here is the start of the class I tested:

public class ShaderInput {

    private /* final */ float[] input;
    private /* final */ int[] strides;


    public ShaderInput()
    {
        this.input = new float[10];
        this.strides = new int[] { 0, 4, 8 };
    }


    public ShaderInput x(int stride, float val)
    {
        input[strides[stride] + 0] = val;
        return this;
    }

    // more stuff ...

And this is the method I used to test the performance of various alternatives, amongst which the ShaderInput class:

public static void test4()
{
	int arraySize = 10;
	float[] fb = new float[arraySize];
	for (int i = 0; i < arraySize; i++) {
		fb[i] = random.nextFloat();
	}
	int times = 1000000000;
	for (int i = 0; i < 10; ++i) {
		floatVectorTest(times, fb);
		arrayCopyTest(times, fb);
		shaderInputTest(times, fb);
		directFloatArrayTest(times, fb);
		System.out.println();
		System.gc();
	}
}

After the 3rd iteration, with the VM warmed up, I consistently got these figures without the final key word:

Simple array copy took   : 02.64
System.arrayCopy took    : 03.20
ShaderInput took         : 00.77
Unsafe float array took  : 05.47

With the final keyword:

Simple array copy took   : 02.66
System.arrayCopy took    : 03.20
ShaderInput took         : 02.59
Unsafe float array took  : 06.24

Note the figures for the ShaderInput test.

It didn't matter whether I made the fields public or private.

Incidentally, there are a few more baffling things. The ShaderInput class outperforms all other variants, even with the final keyword. This is remarkable b/c it basically is a class wrapping a float array, while the other tests directly manipulate the array. Have to figure this one out. May have something to do with ShaderInput's fluent interface.

Also System.arrayCopy actually apparently is somewhat slower for small arrays than simply copying elements from one array to the other in a for loop. And using sun.misc.Unsafe (as well as direct java.nio.FloatBuffer, not shown here) performs abysmally.

Solution 12 - Java

final keyword can be used in five ways in Java.

  1. A class is final
  2. A reference variable is final
  3. A local variable is final
  4. A method is final

A class is final: a class is final means we cannot be extended or inheritance means inheritance is not possible.

Similarly - A object is final: some time we does not modified the internal state of object so in such case we can specify the object is final object.object final means not variable also final.

Once reference variable is made final, it cannot be reassigned to other object. But can change the contents of the object as long as its fields are not final

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
QuestionAbhishek JainView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavarustyxView Answer on Stackoverflow
Solution 3 - Javamel3kingsView Answer on Stackoverflow
Solution 4 - JavawmitchellView Answer on Stackoverflow
Solution 5 - JavaEugeneView Answer on Stackoverflow
Solution 6 - JavasleskeView Answer on Stackoverflow
Solution 7 - JavaNeowizardView Answer on Stackoverflow
Solution 8 - JavaBill KView Answer on Stackoverflow
Solution 9 - Javauser13752845View Answer on Stackoverflow
Solution 10 - JavaCrozinView Answer on Stackoverflow
Solution 11 - Javauser3663845View Answer on Stackoverflow
Solution 12 - JavaadityarajView Answer on Stackoverflow