Calling principles of overloading and rewriting for java method calls (1)

Source: Internet
Author: User

Calling principles of overloading and rewriting for java method calls (1)

Some time ago, I read the content of the third part of the virtual machine execution subsystem in "deep understanding JVM", and saw the calling principles of heavy load and rewriting at the JVM level (see the 8.3 method call section for details ), however, I did not write a blog summary. I will discuss it here. During the discussionBytecode instructionsRelated content.

Conclusion

1. overload method
The call to the overload method mainly depends on the static type, and the parameter method of the static type.
2. override Method
The calling of the rewrite method mainly depends on the actual type. If the actual type implements this method, the method is called directly. If the method is not implemented, search from low to high in the inheritance relationship is not implemented.
3.
The compilation process of java files does not involve the connection process of Traditional compilation.All method calls store only symbolic references in the class file, rather than the entry address in the memory layout of the method during actual running.

Basic Concepts

1. Static and actual types, method Receiver

Human man = new Man();man.foo();

In the preceding statement, the static type of man is Human, and the actual type is Man. The method receiver refers to the owner of the foo () method to be executed (in polymorphism, it may be the object of the parent class Human or the object of the subclass Man ).
2. bytecode method call command
(1) invokestatic: Call a static method
(2) invokespecial: Call the instance constructor method, private method, and parent class method.
(3) invokevirtual: Call all virtual methods.
(4) invokeinterface: Call an interface method and determine an object to implement this interface at runtime.
(5) invokedynamic: The method referenced by the call point qualifier is dynamically parsed at runtime, and then the method is executed.
The first two commands (invokestatic, invokespecial) can resolve the symbol reference to direct reference when the class is loaded, the static methods, instance constructor methods, private methods, and parent methods that meet this condition are called non-virtual methods.
Non-virtual MethodIn addition to the above static methods, instance constructor methods, private methods, and parent methodsFinal Method. Although the final method is called using the invokevirtual command, the final method cannot be overwritten, and there are no other versions. You do not need to perform multi-state selection on the method receiver, or the result of multi-state selection is unique.

Heavy Load

The static and dynamic types mentioned above can be changed. When the static type changes (forced type conversion), the compiler knows that the compiler knows the final static type of the object. When the actual type changes (the object points to another object), the compiler is unknown and can only be seen at runtime.

// Static type change sr. sayHello (Man) man); sr. sayHello (Woman) man); // actual type change Human man = new Man (); man = new Woman ();

The overload only applies to the selection of static types.
The test code is as follows:

/** * Created by fan on 2016/3/28. */public class StaticDispatcher {    static class Human {}    static class Man extends Human {}    static class Woman extends Human {}    public void sayHello(Human human) {        System.out.println("Hello guy!");    }    public void sayHello(Man man) {        System.out.println("Hello man!");    }    public void sayHello(Woman woman) {        System.out.println("Hello woman!");    }    public static void main(String[] args) {        StaticDispatcher staticDispatcher = new StaticDispatcher();        Human man = new Man();        Human woman = new Woman();        staticDispatcher.sayHello(man);        staticDispatcher.sayHello(woman);        staticDispatcher.sayHello((Man)man);        staticDispatcher.sayHello((Woman)man);    }}

First, let's look at the execution result:

It can be seen that when the static type changes, the method of the corresponding type is called. However, when the Man forced type is converted to Woman, there is no compilation error, but there is a runtime exception. "ClassCastException" class ing exception.
Look at the bytecode command:
Javap-verbZ success? Http://www.bkjia.com/kf/ware/vc/ "target =" _ blank "class =" keylink "> vc2uglwmgu3rhdgljrglzcgf0y2hlc1_vcd4ncjxwcmugy2xhc3m9" brush: java; ">public static void main(java.lang.String[]);Code:Stack=2, Locals=4, Args_size=10: new #7; //class StaticDispatcher3: dup4: invokespecial #8; //Method " ":()V7: astore_18: new #9; //class StaticDispatcher$Man11: dup12: invokespecial #10; //Method StaticDispatcher$Man." ":()V15: astore_216: new #11; //class StaticDispatcher$Woman19: dup20: invokespecial #12; //Method StaticDispatcher$Woman." ":()V23: astore_324: aload_125: aload_226: invokevirtual #13; //Method sayHello:(LStaticDispatcher$Human;)V29: aload_130: aload_331: invokevirtual #13; //Method sayHello:(LStaticDispatcher$Human;)V34: aload_135: aload_236: checkcast #9; //class StaticDispatcher$Man39: invokevirtual #14; //Method sayHello:(LStaticDispatcher$Man;)V42: aload_143: aload_244: checkcast #11; //class StaticDispatcher$Woman47: invokevirtual #15; //Method sayHello:(LStaticDispatcher$Woman;)V50: return

We can see that the command checkCast will be called during forced type conversion, and the call method of the invokevirtual command has also changed.39: invokevirtual #14; //Method sayHello:(LStaticDispatcher$Man;)V.
When a VM (accurately called a compiler) is overloaded, it uses the static type of the parameter instead of the actual type as the judgment basis.
For literal types, the compiler automatically converts the types. The conversion sequence is as follows:
Char-int-long-float-long-Character-Serializable-Object
The Character is converted to Character because of automatic packing and to Serializable because Character implements the Serializable interface.

Override

The test code is as follows:

/** * Created by fan on 2016/3/29. */public class DynamicDispatcher {    static abstract class Human {        protected abstract void sayHello();    }    static class Man extends Human {        @Override        protected void sayHello() {            System.out.println("Man say hello");        }    }    static class Woman extends Human {        @Override        protected void sayHello() {            System.out.println("Woman say hello");        }    }    public static void main(String[] args) {        Human man = new Man();        Human woman = new Woman();        man.sayHello();        woman.sayHello();        man = new Woman();        man.sayHello();    }}

Execution result:

Take a look at the bytecode command:

public static void main(java.lang.String[]);  Code:   Stack=2, Locals=3, Args_size=1   0:   new     #2; //class DynamicDispatcher$Man   3:   dup   4:   invokespecial   #3; //Method DynamicDispatcher$Man."
  
   ":()V   7:   astore_1   8:   new     #4; //class DynamicDispatcher$Woman   11:  dup   12:  invokespecial   #5; //Method DynamicDispatcher$Woman."
   
    ":()V   15:  astore_2   16:  aload_1   17:  invokevirtual   #6; //Method DynamicDispatcher$Human.sayHello:()V   20:  aload_2   21:  invokevirtual   #6; //Method DynamicDispatcher$Human.sayHello:()V   24:  new     #4; //class DynamicDispatcher$Woman   27:  dup   28:  invokespecial   #5; //Method DynamicDispatcher$Woman."
    
     ":()V   31:  astore_1   32:  aload_1   33:  invokevirtual   #6; //Method DynamicDispatcher$Human.sayHello:()V   36:  return
    
   
  

From the bytecode, we can see that they call the same method.invokevirtual #6; //Method DynamicDispatcher$Human.sayHello:()VBut the execution result shows that different methods are called. In the compilation phase, the compiler only knows the static type of the object, but does not know the actual type. Therefore, in the class file, it is only necessary to call the method of the parent class. However, the actual type of the object is determined during execution. If the actual type implements this method, it is called directly. If the method is not implemented, it is retrieved from the bottom up based on the inheritance relationship. If the method is not retrieved, throw an exception (Can it be compiled through).

(1) The test code is as follows:

/** * Created by fan on 2016/3/29. */public class Test {    static class Human {        protected void sayHello() {            System.out.println("Human say hello");        }        protected void sayHehe() {            System.out.println("Human say hehe");        }    }    static class Man extends Human {        @Override        protected void sayHello() {            System.out.println("Man say hello");        }//        protected void sayHehe() {//            System.out.println("Man say hehe");//        }    }    static class Woman extends Human {        @Override        protected void sayHello() {            System.out.println("Woman say hello");        }//        protected void sayHehe() {//            System.out.println("Woman say hehe");//        }    }    public static void main(String[] args) {        Human man = new Man();        man.sayHehe();    }}

The test results are as follows:

Bytecode instructions:

public static void main(java.lang.String[]);  Code:   Stack=2, Locals=2, Args_size=1   0:   new     #2; //class Test$Man   3:   dup   4:   invokespecial   #3; //Method Test$Man."
  
   ":()V   7:   astore_1   8:   aload_1   9:   invokevirtual   #4; //Method Test$Human.sayHehe:()V   12:  return
  

The bytecode command is essentially different from the bytecode command in the above Code.

(2) The test code is as follows:

/** * Created by fan on 2016/3/29. */public class Test {    static class Human {        protected void sayHello() {        }    }    static class Man extends Human {        @Override        protected void sayHello() {            System.out.println("Man say hello");        }        protected void sayHehe() {            System.out.println("Man say hehe");        }    }    static class Woman extends Human {        @Override        protected void sayHello() {            System.out.println("Woman say hello");        }        protected void sayHehe() {            System.out.println("Woman say hehe");        }    }    public static void main(String[] args) {        Human man = new Man();        man.sayHehe();    }}

Compilation error:

This example illustrates:The Java compiler performs checks based on static types.

Modify the Error Code as follows:

/** * Created by fan on 2016/3/29. */public class Test {    static class Human {        protected void sayHello() {            System.out.println("Human say hello");        }//        protected void sayHehe() {//            System.out.println("Human say hehe");//        }    }    static class Man extends Human {        @Override        protected void sayHello() {            System.out.println("Man say hello");        }        protected void sayHehe() {            System.out.println("Man say hehe");        }    }    static class Woman extends Human {        @Override        protected void sayHello() {            System.out.println("Woman say hello");        }        protected void sayHehe() {            System.out.println("Woman say hehe");        }    }    public static void main(String[] args) {        Man man = new Man();        man.sayHehe();    }}

Note that the Main method is changedMan man = new Man();
The execution result is as follows:

The bytecode command is as follows:

public static void main(java.lang.String[]);  Code:   Stack=2, Locals=2, Args_size=1   0:   new     #2; //class Test$Man   3:   dup   4:   invokespecial   #3; //Method Test$Man."
  
   ":()V   7:   astore_1   8:   aload_1   9:   invokevirtual   #4; //Method Test$Man.sayHehe:()V   12:  return
  

Note the above bytecode instructionsinvokevirtual #4; //Method Test$Man.sayHehe:()V.

Conclusion

This article discusses the basic principles of heavy load and rewriting, and views the relevant bytecode commands. The next blog post is about single dispatch and multi-dispatch for java method calls (2) about single dispatch and multi-Dispatch.

References: Zhou Zhiming deep understanding of Java Virtual Machine

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.