Many books said that java final instance methods(not private) use static binding, and other instance methods(not private) use dynamic binding. However When compiled, both of them use "invokevirtual" JVM instruction. Do final methods and non final methods are distinguished When JVM executes "invokevirtual" instructions ? I originally think that final methods use "invokespecial" as private instance methods because they all use static binding.
2 Answers
The compiled form is a direct consequence of JLS §13.4.17 in the chapter 13, “Binary Compatibility”:
13.4.17.
final
MethodsChanging a method that is declared
final
to no longer be declaredfinal
does not break compatibility with pre-existing binaries.
This implies that the form of the caller should not reflect whether the target method was final
at compile time or not (or when there was a different representation, it was not allowed to make a practical difference at runtime).
To compare with other forms of invocations, it is not possible to remove a static
modifier without breaking compatibility with callers, hence, it is consistent to encode the form of invocation with a dedicated invokestatic
instruction.
For invocations of private
methods, the caller has to be in the same class, hence, gets recompiled when adding or removing a private
modifier (considering valid callers only), so there’s no problem using invokespecial
when invoking a private
method within the same class. Since JDK 11, private
methods might get invoked by callers in other classes belonging to the same nest group; in that case, these callers in other classes do not use invokespecial
.
So the distinction between final
and non-final
methods does indeed happen at runtime, when the JVM knows the actual target method, if such a distinction happens at all. A conforming JVM has to reject classes trying to override a final
method, but they don’t need to perform optimizations regarding invocations. In practice, today’s JVMs are capable of optimizing invocations of all methods that have not been overridden, regardless of whether this properties has been enforced by a final
modifier. The only difference is that loading a new class into the JVM that does override a non-final
method may cause de-optimization of the callers.
There is no other bytecode instruction to call an instance method declared by a class other than invokevirtual
. Its name is confusing. It could also be named like invokeClassMethod
or invokeclass
. Actually compiler does not treat final methods specially. invokespecial
is used to invoke constructors and static initializers.

- 6,180
- 4
- 31
- 51
-
2Not strictly true. You can `invokespecial` just fine on normal methods and this is done for super calls for example. – yawkat May 25 '18 at 10:21