Is it possible to determine the binding type of a method by bytecode?
From the following sources:
https://www.amazon.com/Java-Complete-Reference-Herbert-Schildt/dp/0071808558
Chapter 8: Using final with Inheritance
http://javarevisited.blogspot.com.by/2012/03/what-is-static-and-dynamic-binding-in.html
Static Vs. Dynamic linking in Java
for private, static, final methods of the early (static) binding method should use
... So I created a small test
class MethodRefDemo2
{
public static void main( String args[] )
{
BindingTest bindingTest = new BindingTest();
bindingTest.printEarly();
bindingTest.printLate();
}
}
class BindingTest
{
private String early = "static";
private String late = "dynamic";
final String printEarly()
{
return early;
}
String printLate()
{
return late;
}
}
So, as I think these two methods should have different types of bindings. Byte code check:
public static main([Ljava/lang/String;)V
L0
LINENUMBER 8 L0
NEW spring/BindingTest
DUP
INVOKESPECIAL spring/BindingTest.<init> ()V
ASTORE 1
L1
LINENUMBER 9 L1
ALOAD 1
INVOKEVIRTUAL spring/BindingTest.printEarly ()Ljava/lang/String;
POP
L2
LINENUMBER 10 L2
ALOAD 1
INVOKEVIRTUAL spring/BindingTest.printLate ()Ljava/lang/String;
POP
L3
LINENUMBER 11 L3
RETURN
L4
LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
LOCALVARIABLE bindingTest Lspring/BindingTest; L1 L4 1
MAXSTACK = 2
MAXLOCALS = 2
Here I see two INVOKEVIRTUAL instructions. So, is there a way to determine what type of binding was used in the byte code of the class? And if not, how can I determine the type of binding?
source to share
The phrase "From java spec" is misleading as there are no multiple specs, so only Java specification that does not contain the quoted operator.
The terms early binding and late binding are not sufficient to describe the capabilities of Java method calls.
-
The only method calls whose ultimate purpose is permitted at compile time are methods
private
and calls to the constructor and, since Java 8 method calls,static
for typesinterface
. -
Calling the method
static
on non-typesinterface
and calling the methodsuper
at compile time will set the target type, but the JVM can resolve the method to the supertype of the specified type at runtime. However, this resolved target method will never change in a particular runtime and should not be allowed for every method invocation, so its some early binding once the method is resolved. But JVMs usually defer permission until the first actual execution of the calling command. -
For other types of instances of instance methods, it does not matter whether the target method was declared
final
at compile time or not. These calls are always coded in the same way as a statementinvokevirtual
, which implies finding the actual target method based on the type of the receiver object. You can change the method tofinal
or notfinal
after compiling the caller without breaking compatibility (unless you override the method that was subsequentlyfinal
called to ).When the receiver type is
interface
, it can never be readfinal
at compile time, but still ends up using the methodfinal
at run time.Of course, after resolving, the JVM may notice that the target method has been declared
final
and refer to the optimized match of the "early binding" binding of the second kind above, on the other hand, most JVMs are smart enough to do the same with methods that were not declaredfinal
, but still not overridden (which might apply to most of all methods). Therefore, it would be pointless to call anfinal
early binding method call if the only consequence is optimization applied to other methods.
source to share