Java static Dispatch and dynamic Dispatch (II.)

Source: Internet
Author: User

The method invocation is not equal to the method execution, the only task in the method invocation phase is to determine the version of the called method (that is, which method is called), and for the time being, does not involve a specific running procedure inside the method.

When the program is running, the method call is the most common, most frequent operation, but the class file compilation process does not include the traditional compilation of connection steps, all method calls in the class file is stored in the symbol reference only , Instead of the entry address of the method in the actual run-time memory layout (relative to the previously mentioned direct reference). This feature gives Java more powerful dynamic scalability, but also makes the Java method invocation process relatively complex, requiring a direct reference to the target method during class loading , and even during runtime .

Analytical

The target method in all method calls is a reference in a constant pool within the class file, and some of the symbolic references are converted to direct references during the parsing phase of the load. The premise of this resolution is that the method has a deterministic version of the call before the program is actually executed, and that the invocation version of the method is immutable during the run time. In other words, the invocation target must be determined when the program code is written and compiled by the compiler, and the invocation of such a method is called parsing .

In the Java language in accordance with the " compile time known, the runtime is immutable" method, mainly including static methods and private methods two categories, the former is directly related to the type, the latter is not accessible outside, The characteristics of these two methods determine that they cannot be overridden by inheritance or other means to rewrite other versions, so they are suitable for parsing during the class loading phase.

static methods , private methods , instance constructors , and parent class methods . These methods are called non-virtual methods , and they resolve the symbolic reference to a direct reference to the method when the class loads. In contrast, other methods are called virtual methods (except the final method).

Assign a static dispatch

[Java]View PlainCopy
  1. Public class Staticdispatch {
  2. Static abstract class human{
  3. }
  4. static class man extends human{
  5. }
  6. static class Woman extends human{
  7. }
  8. public static void SayHello (Human guy) {
  9. System.out.println ("hello,guy!");
  10. }
  11. public static void SayHello (Mans guy) {
  12. System.out.println ("hello,gentlemen!");
  13. }
  14. public static void SayHello (Woman guy) {
  15. System.out.println ("hello,lady!");
  16. }
  17. public static void Main (string[] args) {
  18. Human man=New Man ();
  19. Human woman=New Woman ();
  20. SayHello (man);
  21. SayHello (woman);
  22. }
  23. }

Output:

hello,guy!
hello,guy!

Human man=new Man ();
We refer to "Human" as the static type of the variable, the following "man" is called the actual type of the variable, the static type and the actual type can be changed in the program, the difference is that the static type changes only when used, the variable The static type of itself is not changed, and the final static type is known in the compiler, and the result of the actual type change is determined at run time, and the compiler does not know what the actual type of an object is at compile time.

[Java]View PlainCopy
    1. Human man=New Man ();
    2. SayHello (man);
    3. SayHello (man); //Type conversion, static type change, we know that the post-transition static type must be man.
    4. man=new Woman (); //actual type change, actual type is indeterminate
    5. SayHello (man);
    6. SayHello ((Woman) man); //Type conversion, static type change

Output:

hello,guy!
hello,gentlemen!
hello,guy!
hello,lady!

When overloaded , the compiler is judged by the static type of the parameter rather than by the actual type. And the static type is known at compile time, so during the compile phase, the Javac compiler determines which overloaded version to use based on the static type of the parameter .

All dispatch actions that rely on static types to locate a method's execution version are called static allocations . A typical application for static dispatch is method overloading .

Static dispatch occurs during the compilation phase, so determining the statically dispatched action is not actually performed by the virtual machine, but is done by the compiler.

However, the literal does not show a static type , its static type can only be understood and inferred by the rules of the language.

[Java]View PlainCopy
  1. Public class Literaltest {
  2. /**/  
  3. public static void SayHello (char arg) {
  4. System.out.println ("Hello char");
  5. }
  6. public static void SayHello (int arg) {
  7. System.out.println ("Hello int");
  8. }
  9. public static void SayHello (long Arg) {
  10. System.out.println ("Hello Long");
  11. }
  12. public static void SayHello (Character arg) {
  13. System.out.println ("Hello Character");
  14. }
  15. public static void Main (string[] args) {
  16. SayHello (' a ');
  17. }
  18. }

Output:

Hello Char
The overloaded method is commented from top to bottom, and a different output is obtained.

If the compiler cannot determine which type to customize to transition to, the type is ambiguous and the compilation is rejected.

[Java]View PlainCopy
  1. Import Java.util.Random;
  2. Public class Literaltest {
  3. /**/  
  4. public static void SayHello (String arg) {//new overloaded method
  5. System.out.println ("Hello String");
  6. }
  7. public static void SayHello (char arg) {
  8. System.out.println ("Hello char");
  9. }
  10. public static void SayHello (int arg) {
  11. System.out.println ("Hello int");
  12. }
  13. public static void SayHello (long Arg) {
  14. System.out.println ("Hello Long");
  15. }
  16. public static void SayHello (Character arg) {
  17. System.out.println ("Hello Character");
  18. }
  19. public static void Main (string[] args) {
  20. Random r=new Random ();
  21. String s="abc";
  22. int i=0;
  23. SayHello (R.nextint ()%2!=0?s:i); Compile error
  24. SayHello (R.nextint ()%2!=0?' A ':false); //Compilation error
  25. }
  26. }

Dynamic Dispatch

[Java]View PlainCopy
  1. Public class Dynamicdispatch {
  2. Static abstract class human{
  3. protected abstract void SayHello ();
  4. }
  5. static class man extends human{
  6. @Override
  7. protected void SayHello () {
  8. System.out.println ("man say Hello!");
  9. }
  10. }
  11. static class Woman extends human{
  12. @Override
  13. protected void SayHello () {
  14. System.out.println ("woman say Hello!");
  15. }
  16. }
  17. public static void Main (string[] args) {
  18. Human man=New Man ();
  19. Human woman=New Woman ();
  20. Man.sayhello ();
  21. Woman.sayhello ();
  22. man=new Woman ();
  23. Man.sayhello ();
  24. }
  25. }

Output:
Mans say hello!
Woman say hello!
Woman say hello!

Obviously, it is not possible to decide on the static type again, because the static type is also the two variables of the human man and woman perform different behavior when invoking the SayHello () method, and the variable man executes a different method in two calls. The cause of this phenomenon is obvious, is the actual type of the two variables, how the Java virtual machine according to the actual type to dispatch the method execution version of it?
Starting with the polymorphic discovery process of the invokevirtual directive, the runtime parsing process of theinvokevirtual Directive is broadly divided into the following steps:

1. Find the actual type of the object pointed to by the first element at the top of the operand stack, as C.
2. If a method in type C that matches the descriptor and simple name in the constant is found, then access validation is performed, and if the validation is passed the direct reference to the method is returned, the lookup process ends; The Java.lang.IllegalAccessError exception is thrown.
3, otherwise not found, according to the inheritance relationship from the next to the type C of each parent class for the 2nd step of the search and validation process.
4, if not always find the right method, then run out of Java.lang.AbstractMethodError exception.

Since the first step in the execution of the invokevirtual instruction is to determine the actual type of receiver at run time, the invokevirtual instruction in two calls resolves the class method symbol reference in the constant pool to a different , This process is the essence of the Java language method rewrite . We call this dispatch process, which executes versions based on the actual type determination method at run time, as dynamic dispatch .

Implementation of dynamic dispatch of virtual machine

The dispatch process described earlier, as an analysis of the virtual machine conceptual model, is basically sufficient to solve the problem of what the virtual machine "will do" in dispatch.

However, virtual machines "specifically how to do", there may be a variety of virtual machine implementation will be some difference.

Because dynamic dispatch is a very frequent action, and the dynamically dispatched method version selection process requires the runtime to search for the appropriate target method in the method metadata of the class, the actual implementation of the virtual machine is based on performance considerations, and most implementations do not really carry out such frequent searches. In this case, the most commonly used "stability optimization" approach is to create a virtual method table (virtual table, also known as vtable) for the class in the method area, using the virtual Method table index instead of the metadata find to improve performance.

The virtual method table holds the actual entry address of each method. If a method is not overridden in a subclass, the address entry in the virtual method table of the subclass and the address entry for the same method as the parent class are consistent, pointing to the actual entry of the parent class. If this method is overridden in a subclass, the address in the subclass method table will be replaced with the entry address that points to the actual version of the subclass.

For the convenience of the implementation of the program, with the same signature method, the parent class, the subclass of the virtual method table has the same index number , so when the type transformation, only need to change the method table lookup, you can from the different virtual method table by index to convert the required entry address.

The method table is typically initialized during the join phase of the class loading phase, and after the class's variable initial value is prepared, the virtual opportunity initializes the method table for that class.

Content from:

"In-depth understanding of Java virtual machines"

Transferred from: http://blog.csdn.net/sunxianghuang/article/details/52280002

Java static Dispatch and dynamic Dispatch (II.)

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.