I read that declaring a method as final leads to performance enhancement. So, doesn't it make sense to declare methods that are not expected to be overridden as final? My question is specifically about the improvement in performance and any associated cons of such usage.
I read that declaring a method as final leads to performance enhancement.
That is incorrect for recent HotSpot JIT compilers. My understanding is that the JIT compiler looks at all currently loaded classes to determine whether there is any overriding for each method that it compiles. If none is found, then the JIT compiler treats the method as if it was final1.
So, declaring methods final as an optimization does not make sense.
(This may not apply to all Java platforms; e.g. non-HotSpot platforms with a primitive JIT compiler.)
A better use of final on a method is when you want / need to forbid certain kinds of extension of your classes by subclassing. Whether / when to do this is a matter of opinion. I certainly wouldn't do this "as a matter of course".
1 - A HotSpot JIT compiler will even recompile previously compiled classes if dynamic loading introduces a new subclass that overloads a method that was previously not overridden.
So, doesn't it make sense to declare methods that are not expected to
be overridden as final?
I don't believe so. The final keyword is saying that this method can't be overridden (for security reasons for example), not that the original developer doesn't expect that you'd want to override it. That would be very presumptuous and definitely reduce the extensibility of APIs.
As mentioned in the other answer, I wouldn't expect it to make any difference to performance and if it did, you wouldn't notice!
Related
I recently read this article by Jake Wharton. This is targeted at Android, but also perfectly valid for java I think.
Consider the following code:
public class A {
private String someField = "abc";
class B {
public void doSomething() {
System.out.println(someField);
}
}
}
We have a simple class A and an inner class B (This has a reference to A and can acccess its members). Class B is accessing the field someField in A even though it is private. According to the article, this is done by the compiler generating synthetic accessor methods which allow the inner class to access the field.
Now my way more basic question: Why does the compiler even care about visiblities when the code is compiled? As we have seen in this example, a new method is generated, which basically just introduces overhead.
Visibilities are a great thing for architecting good software, but if the compiler is done checking that everything is correct according to the declared visibilies, why not optimize those methods away (E.g. just taking everything for being public and allow calls to it)?
First I thought this was due to security reasons, but reflection allows the access of all fields, not caring for visibility as far as I know.
This might be a basic misunderstanding of me, if so, I would be happy if someone could explain it to me.
Why does the compiler even care about visiblities when the code is compiled?
The JVM doesn't allows access to private methods/constructors/fields outside a class. It has no special rule for nested classes which were added after this rule was designed. Instead the compiler adds accessor methods so the language can support a means of access the JVM doesn't.
As we have seen in this example, a new method is generated, which basically just introduces overhead.
Only if the method isn't called very much and isn't optimised.
Adding any simple method (On Hotspot, any method of 35 bytes or less) will be inlined very quickly and has no impact on performance (except if the maximum inline level is reached)
why not optimize those methods away
It does this at runtime so that previous rules continue to be enforced.
reflection allows the access of all fields, not caring for visibility as far as I know.
Though not by default, you have to explicitly want this as an option and not have a SecurityManager which prevents it.
If compiler converts all private fields to public fields in compile time, one problem will be happened when your project is compiled into library and reused by others. In that case, all your private fields will become public.
There are some tools for optimizing this. In Android, there is a tool named ProGuard that will convert all getter/setter to direct field access.
While declaring a class as final , we cannot Inheritance this class , my question is why ? - from the java internals perspective.
I assume that the same principle apply to methods and instance as well.
is it somehow related to the class loader as well ? who is actually stopping me from override it?
There's nothing related to the JVM or internals (not really sure what exaclty you mean by that), it's a compile issue simply because you're breaking the rules.
If I think myself as a Java compiler, after parsing the tokens in your code I'm just going to look around for logical errors (semantic analysis) e.g. a circular inheritance scheme. The moment I see someone's attempt at extending a final class, I'm gonna go bazooka. That's it. No need to wake up the big bosses, the JVM or any other internals because the program cannot be correctly compiled in the first place.
If you want to know how the compiler works the way it does internally, think that while the compiler parses your code, it creates and fills some structures internal to itself for the purpose of error-checking and bytecode-translation. Also imagine in a simplified scenario that the final keyword attached to a class just sets a field in one of these structures attached to your class. After syntactic analysis, the compiler goes on with "logical" (semantic) analysis and checks (among other things) if some lunatic tries extending a final class. Even a brute search in an inheritance graph can pull that off. If a class is final and still has children, halt and notify the lunatic. The issue won't get more internal than the compiler.
It is nothing to do with Java internals.
The purpose of declaring a class to be final it to prevent it from being subclassed.
My question was what happening "underground" while declaring final ...
Well ... when a class is declared as final a flag is set in the class file to say this. If you then attempt to load a class that purports to be a subclass of a final class, the classloader will throw a VerifyError exception. The checks are done in the ClassLoader.defineClass(...) methods ... which are also final, so that normal programs can't interfere with them.
This aspect of classfile verification needs to be watertight for Java security reasons. If it wasn't then you could probably cause mayhem in a Java security sandbox by tricking trusted code into using (say) a mutable subtype of String.
The Java compiler also checks that you don't extend a final class, but you could subvert that by (for example) creating ".class" files by hand. Hence the need for load-time checks ...
Who is actually stopping me from override it?
Actually, it is the classloader. See above.
Let's look at it elementally, When you declare a variable as final, you did that because you don't want the value of that variable be changed for any reason afterwards, Right?.
Okay, under the assumption that you agree to that. The same principle is also applicable to classes.
Let's look at it this way: Why will you ever want to inherit a class? Probably because you want get access to the properties of the class and her behaviors (methods), Right? Once you have inherited these properties and behaviors you have the right the modify the accessible behavior to suite your precise need without having to re-implement all other behaviors. This is the value and power of in inheritance.
Hence, declaring a class as final implies that you don't want anyone to modify any behavior of the class. You tries to state that who so ever that will want use your class should use it as IS.
Therefore, any attempt to modify a final class is illogical and should be considered as error.
Eg.
Imaging if someone should be able to inherit your final Authentication class and modifying the actual authentication behavior (method). This should be a security bridge as it might compromise your reasons for setting the class as final.
Hence, it is a design practice.
I hope that make some sense?
My question is pretty simple:
Does the compiler treat all the methods in a final class as being final themselves? Does adding the final keyword to methods in a final class has any effect?
I understood that final methods have a better chance of getting inlined and this is why I am asking.
Thanks in advance.
You're correct, all methods in a final class are implicitly final.
See here:
"Note that you can also declare an entire class final. A class that is
declared final cannot be subclassed. This is particularly useful, for
example, when creating an immutable class like the String class."
And here:
All methods in a final class are implicitly final.
This may also be of interest for you: Performance tips for the Java final keyword
Does the compiler treat all the methods in a final class as being final themselves?
In effect, yes it does. A method in a final class cannot be overridden. Adding (or removing) a final keyword to a method makes no difference to this rule.
Does adding the final keyword to methods in a final class has any effect?
In practice, it has minimal effect. It has no effect on the rules on overriding (see above), and no effect on inlining (see below).
It is possible to tell at runtime if a method was declared with a final keyword ... using reflection to look at the method's flags. So it does have some effect, albeit an effect that it irrelevant to 99.99% of programs.
I understood that final methods have a better chance of getting inlined and this is why I am asking.
This understanding is incorrect. The JIT compiler in a modern JVMs keeps track of which methods are not overridden in the classes loaded by an application. It uses this information, and the static types to determine whether a particular call requires virtual class dispatching or not. If not, then inlining is possible, and will be used depending on how large the method body is. In effect, the JIT compiler ignores the presence / absence of final, and uses a more accurate method to detect method calls where inlining of the method is allowable.
(In fact it is more complex than this. An application can dynamically load subclasses that cause the JIT compiler's method override analysis to become incorrect. If this happens, the JVM needs to invalidate any effected compiled methods and cause them to be recompiled.)
The bottom line is:
There is NO performance advantage in adding final to methods in final classes.
There might be a performance advantage in final to methods in non-final classes, but only if you are using an old Sun JVM, or some other Java / Java-like platform with a poor quality JIT compiler.
If you care about performance, it is better to use an up-to-date / high performance Java platform with a decent JIT compiler than to pollute your code-base with final keywords that are liable to cause you problems in the future.
You wrote in a comment:
#RussellZahniser I have read differently in many places.
The internet is full of old information, much of which is out of date ... or was never correct in the first place.
May be the compiler treats them as final.
The following prints "false":
final class FinalClass {
public void testMethod() {}
}
Method method = FinalClass.class.getDeclaredMethod("testMethod");
int m = method.getModifiers();
System.out.println(Modifier.isFinal(m));
As the source of the ActivityThread class shows, it's a final class, and all the methods in this class is also final methods. As the final keyword definition in java, this class cannot be inherited, but why android developers keep those methods final ?
Maybe I didn't express the question clear, I fix it here.
ActivityThread is a final class, it will not have any sub-class, and no method will be overridden, but you know that all the methods in this class is final , I want to know why they need these final keywords, they can remove them with no impact.
The Java Language Specification makes it clear that no method of a final class can be overridden. Thus, the final declaration on the methods appear to be redundant. (Maybe left over from a beta version of the Android API when ActivityThread was perhaps not a final class?)
On the other hand, optimizers and obfuscators can sometimes do a little more with methods declared final. Although they ought to be smart enough to make the inference that a final class won't have any overridden methods, it can't hurt to give them the extra hint.
why android developers keep those methods final?
Actually, the Java engineers did that. It's a design decision: sometimes you want to prohibit sub-classing one of your classes. Why? Some of the reason is that it implies some strong responsibility, that forces you to take very smart decisions.
Let me reference part of the item number 17 of Effective Java Second Edition by Joshua Bloch:
So what does it mean for a class to be designed and documented for inheritance?
First, the class must document precisely the effects of overriding any method. In other words, the class must document its self-use of overridable methods. For each public or protected method or constructor, the documentation must indicate which overridable methods the method or constructor invokes, in what sequence, and how the results of each invocation affect subsequent processing. (By overridable, we mean nonfinal and either public or protected.) More generally, a class must document any circumstances under which it might invoke an overridable method. For example, invocations might come from background threads or static initializers.
...
Design for inheritance involves more than just documenting patterns of self- use. To allow programmers to write efficient subclasses without undue pain, a class may have to provide hooks into its internal workings in the form of judi- ciously chosen protected methods or, in rare instances, protected fields.
Quoting from http://sites.google.com/site/gson/gson-design-document:
Why are most classes in Gson marked as
final?
While Gson provides a fairly
extensible architecture by providing
pluggable serializers and
deserializers, Gson classes were not
specifically designed to be
extensible. Providing non-final
classes would have allowed a user to
legitimately extend Gson classes, and
then expect that behavior to work in
all subsequent revisions. We chose to
limit such use-cases by marking
classes as final, and waiting until a
good use-case emerges to allow
extensibility. Marking a class final
also has a minor benefit of providing
additional optimization opportunities
to Java compiler and virtual machine.
Why is this the case? [If I would guess: of JVM knows class is final it does not maintain method override tables? Are there any other reasons?]
What is the benefit in performance?
Does this applies to classes that are frequency instantiated (POJO?) or perhaps to class that are holders static methods (Utility classes) ?
Are methods defined as final also can theoretically improve performance?
Are there any implications?
Thank you,
Maxim.
Virtual (overridden) methods generally are implemented via some sort of table (vtable) that is ultimately a function pointer. Each method call has the overhead of having to go through that pointer. When classes are marked final then all of the methods cannot be overridden and the use of a table is not needed anymore - this it is faster.
Some VMs (like HotSpot) may do things more intelligently and know when methods are/are not overridden and generate faster code as appropriate.
Here is some more specific info on HotSpot. And some general info too.
An old, apparently no longer but still largely relevant, article on this from IBM developerWorks, which states:
The common perception is that
declaring classes or methods final
makes it easier for the compiler to
inline method calls, but this
perception is incorrect (or at the
very least, greatly overstated).
final classes and methods can be a
significant inconvenience when
programming -- they limit your options
for reusing existing code and
extending the functionality of
existing classes. While sometimes a
class is made final for a good reason,
such as to enforce immutability, the
benefits of using final should
outweigh the inconvenience.
Performance enhancement is almost
always a bad reason to compromise good
object-oriented design principles, and
when the performance enhancement is
small or nonexistent, this is a bad
trade-off indeed.
Also see this related answer on another question. There's also the equivalent question for .Net, discussed here. SO discussion, "Are final methods inlined?" On a question titled "What optimizations are going to be useless tomorrow," this one appears on the list.
Note also that there is an entangling of the effects of final classes vs. final methods. You may get some performance benefit (again, I don't have a good reference) for final methods for sure, as it could cue the JIT to do inlining it couldn't otherwise do (or not so simply). You get the same effect when you mark the class final, which means that all the methods are suddenly final as well. Note that the Sun/Oracle folks claim that HotSpot can usually do this with or without the final keyword. Are there any additional effects from having the class itself final?
For reference, links to the JLS on final methods and final classes.
Not knowing the implementation of every particular JVM, I would theoretically say that if a JVM knows that a pointer to an object is a pointer to a type that is final, it can do non-virtual function calls (i.e., direct vs. indirect) to a member functions (i.e., no indirection through a function pointer), which may result in faster execution. This may also in turn lead to inlinining possibilities.
Marking classes as final allows further optimizations to be applied during the JIT stage.
If you are calling a virtual method on a non-final class, you don't know whether the proper implementation is the one defined in that class, or some sub-class that you don't know about.
However, if you have a reference to a final class, you know the specific implementation that is required.
Consider:
A extends B
B extends C
B myInstance = null;
if(someCondition)
myInstance = new B();
else
myInstance = new C();
myInstance.toString();
In this case, the JIT can't know whether C's implementation of toString() or B's implementation of toString() will be called. However, if B is marked as final, it is impossible for any implementation other than B's to be the proper implementation
No difference, that's just speculation. The only situation where it has sense are classes like String, etc where jvm treat them differently.