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?

+3


source to share


1 answer


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 types interface

    .

  • Calling the method static

    on non-types interface

    and calling the method super

    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 statement invokevirtual

    , which implies finding the actual target method based on the type of the receiver object. You can change the method to final

    or not final

    after compiling the caller without breaking compatibility (unless you override the method that was subsequently final

    called to ).

    When the receiver type is interface

    , it can never be read final

    at compile time, but still ends up using the method final

    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 declared final

    , but still not overridden (which might apply to most of all methods). Therefore, it would be pointless to call an final

    early binding method call if the only consequence is optimization applied to other methods.

+2


source







All Articles