In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article will explain in detail how method calls are used in web development. The content of the article is of high quality, so the editor will share it with you for reference. I hope you will have some understanding of the relevant knowledge after reading this article.
Are you familiar with method calls? Do you really know it? Let's plate it today.
First of all, we should be clear about the concept that the method call here is not that the code in the method is executed, but to determine the version of the method being called, that is, which method will eventually be called.
Analysis
We said earlier that during the parsing phase of class loading, some symbolic references will be converted into direct references. The premise of this parsing is that the method has a determinable calling version before the program actually runs, and the calling version of this method is immutable at run time. We call calls to such methods as Resolution.
Seeing this prerequisite, do any friends associate with the polymorphism of the object? The methods that are not overridden in java include static methods, private methods (which cannot be accessed externally), instance constructors, and methods decorated by final, so they are all suitable for parsing during the class loading phase, while parent class methods called through this or super are also parsed during the class loading phase.
Instruction set
Call different types of methods, set different instructions in the bytecode instruction set, and provide five method invocation bytecode instructions in jvm:
Invokestatic: calls a static method, and determines the unique method version in the parsing phase
Invokespecial: instance constructor init methods, private and parent methods, and determine the unique method version in the parsing phase
Invokevirtual: call all virtual methods
Invokeinterface: call the interface method and determine another object that implements the interface at run time
Invokedynamic: first dynamically parses the method referenced by the call point qualifier at run time, and then executes the method. In the previous four call instructions, the dispatching logic is fixed in the Java virtual machine, while the dispatching logic of the invokedynamic instruction is determined by the boot method set by the user.
Invokedynamic instruction is added in Java7, which is an improvement for dynamically typed language, but the method of generating this instruction is not directly provided in java7. It is necessary to use the underlying bytecode tool of ASM to generate the instruction. It is not until the emergence of the lambda expression of java8 that the instruction is generated directly.
Small knowledge points: statically typed language and dynamically typed language
The difference between them lies in whether the type is checked at compile time or at run time, and the former is statically typed language, on the contrary, dynamically typed language. That is to say, statically typed language is the type information to judge the variable itself, and dynamic typed language is the type information to judge the value of variables. If variables have no type information, variable values have type information, which is an important feature of dynamic languages.
The basic data type defined in the "example" java class has already determined its specific type at the time of declaration, while JS uses var to define the type, and the type that the value is will be used in the call.
Virtual method and non-virtual method
If the bytecode instruction set is invokestatic, invokespecial, or invokevirtual decorated with final, the unique call version can be determined in the parsing phase, and the five methods mentioned above meet this condition. They resolve symbolic references to direct references to the method when the class is loaded, which can be called "non-virtual methods". On the contrary, the method that is not a non-virtual method is a "virtual method". Picture
Dispatch
If we do not convert the symbolic reference of the method to a direct reference during compilation, but bind the relevant method according to the actual type of the method at run time, we call the call to this method dispatch. Among them, the distribution is divided into static distribution and dynamic distribution.
Static dispatch
I don't know what you know about overloading. To explain static dispatching, let's start with an overloaded quiz:
Public class StaticDispatch {static abstract class Human {static class Man extends Human {} static class Woman extends Human {} public void sayHello (Human guy) {System.out.println ("hello,guy!") ;} public void sayHello (Man guy) {System.out.println ("hello,gentleman!") ;} public void sayHello (Woman guy) {System.out.println ("hello,lady!") ;} public static void main (String [] args) {Human man = new Man (); Human woman = new Woman (); StaticDispatch sr = new StaticDispatch (); sr.sayHello (man); sr.sayHello (woman);}} hello,guy! Hello,guy!
Did you get the right answer? First, let's look at two concepts: static types and actual types. Take Human man = new Man (); for example, Human is called the static type of variable, while Man we call the actual type of variable, the difference is as follows:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
The change of the static type occurs only when it is used, the static type of the variable itself is not changed, and ultimately the static type is known at compile time.
The actual type change is known at run time, and the compiler does not know what the specific type of an object is when compiling the program.
The Human type method is executed here because when overloaded, the compiler uses the "static type" of the parameter as the basis for determining the execution method, rather than using the "actual type".
All dispatching actions that rely on static types to locate the version of a method execution are called static dispatches. A typical application of static dispatch is method overloading. Static dispatch occurs during the compilation phase, so the action of determining static dispatch is actually not performed by the virtual machine, but by the compiler.
Dynamic dispatch
Let's learn about rewriting after learning about overloading. The case begins:
Public class DynamicDispatch {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 ();}}
Please consider the output and remain silent for two minutes. The answer is:
Man say hello! Woman say hello! Woman say hello!
I'm sure everyone got the right result this time, right? Let's first add a point of knowledge:
When a parent class reference points to a subclass, its own method is called if the executed parent class method is not overridden in the subclass; if the subclass is overridden, the subclass method is called. If you want to use subclass-specific properties and methods, you need to transition down.
Based on this conclusion, let's deduce that man and women are variables of the same static type, return different results when calling the same method sayHello (), and execute different methods in two calls to the variable man. The obvious reason for this is that the "actual type" of the two variables is different. how does the Java virtual machine dispatch the method execution version based on the actual type? Let's look at the bytecode file:
Man.sayHello (); woman.sayHello ()
We focus on the above two lines of code, which correspond to 17 and 21 lines of bytecode instructions, respectively. From the point of view of the bytecode instruction alone, the two instructions invokevirtual and the constant $Human.sayHello: () V are exactly the same, but the execution results are really different, so we have to study the invokevirtual instruction. The operation flow is as follows: picture
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Find the actual type of object pointed to by the first element at the top of the Operand stack and write it down as C.
If a method is found in type C that matches both the descriptor and the simple name in the constant, the access permission is verified. If it passes, a direct reference to this method is returned, and the lookup process ends; if it fails, a java.lang.IllegalAccessError exception is returned (an illegal access exception will be reported if it is not under the same jar package).
Otherwise, each parent class of C is searched and verified in step 2 according to the inheritance relationship.
If the appropriate method is never found, a java.lang.AbstractMethodError exception is thrown.
Since the first step in the execution of the invokevirtual instruction is to determine the actual type of the recipient at run time, the invokevirtual instruction in the two calls does not end by parsing the symbolic reference of the method in the constant pool to the direct reference, but also selects the method version based on the actual type of the recipient (the actual types in the case are Man and Woman), which is the "essence" of method rewriting in the Java language.
We refer to this process of dispatching a version of a method based on the actual type at run time as dynamic dispatch.
Single dispatch and multiple dispatch
The receiver of the method and the parameters of the method are collectively referred to as the number of the method, and this definition should be derived from the book Java and patterns. According to the number of dispatches, dispatches can be divided into single dispatches and multiple dispatches. Single dispatch is to select the target method according to one quantity, while multi-dispatch is to select the target method according to more than one quantity.
"give an example"
Public class Dispatch {static class QQ {} static class_360 {} public static class Father {public void hardChoice (QQ arg) {System.out.println ("father choose qq");} public void hardChoice (_ arg) {System.out.println ("father choose 360") }} public static class Son extends Father {public void hardChoice (QQ arg) {System.out.println ("son choose qq");} public void hardChoice (_ 360arg) {System.out.println ("son choose 360");}} public static void main (String [] args) {Father father=new Father (); Father son=new Son () Father.hardChoice (new_360 ()); son.hardChoice (new QQ ());}}
Please consider the output and remain silent for two minutes. The answer is:
Father choose 360 son choose qq
Let's take a look at the compiler selection process during the compilation phase, that is, the process of static dispatch. At this time, the choice of the target method is based on two points: one is whether the static type is Father or Son, and the other is whether the method parameter is QQ or 360. The final result of this selection is the generation of two invokevirtual instructions whose parameters are symbolic references to the Father.hardChoice (360) and Father.hardChoice (QQ) methods in the constant pool. Because the choice is based on two quantities, the static dispatch of the Java language belongs to the type of multi-dispatch.
Then look at the selection of virtual machines at run time, that is, the process of dynamic dispatch. When executing the code "son.hardChoice (new QQ ())", more precisely, when executing the invokevirtual instruction corresponding to this code, since the compilation time has decided that the signature of the target method must be hardChoice (QQ), the virtual machine will not care whether the passed parameter "QQ" is "Tencent QQ" or "Chery QQ". Because the static type and the actual type of the parameter will not affect the choice of the method, the only factor that can affect the choice of the virtual machine is whether the actual type of the recipient of this method is Father or Son. Because there is only one quantity as the basis for selection, the dynamic dispatch of the Java language belongs to the type of single dispatch.
Virtual method table
Dynamic dispatch is frequently used in object-oriented programming, and execution efficiency is likely to be affected if it is necessary to search for appropriate targets in the class's method metadata during each dynamic dispatch. Therefore, in order to improve the performance, jvm uses to build a virtual method table (Vritual Method Table, also known as vtable) in the method area of the class, correspondingly, the interface method table-Inteface Method Table (itable) is also used in the execution of invokeinterface, and the virtual method table index is used instead of metadata lookup to improve performance.
There is a virtual method table in each class that holds the actual entries for various methods:
If a method is not overridden in a subclass, the address entry in the virtual method table of the subclass is the same as that of the same method in the parent class, pointing to the implementation entry of the parent class.
If this method is overridden in the subclass, the address in the subclass method table will be replaced with the entry address that points to the subclass implementation version.
Son rewrites all methods from Father, so Son's method table does not have an arrow pointing to Father type data. But neither Son nor Father overrides methods from Object, so all methods inherited from Object in their method tables point to the data type of Object.
For the convenience of program implementation, the method with the same signature should have the same index number in the virtual method table of the parent class and the subclass, so that when the type is changed, only the method table needs to be changed. the desired entry address can be converted by index from different virtual method tables. The method table is generally initialized in the connection phase of the class load. after the initial values of the variables of the class are prepared, the virtual machine initializes the method table of the class.
Binding mechanism
Parsing calls must be a static process, and it is fully determined during compilation that all symbolic references involved will be converted into determinable direct references during the parsing phase of class loading, and will not be delayed until run time. Dispatch calls can be static or dynamic. Therefore, we call "parsing" and "static dispatching" the called methods during compilation, and the calls that remain unchanged during the run time are called static links, while those that call the methods at run time are called dynamic links.
We convert the conversion in the process of static link to early binding and the transformation in the process of dynamic link to late binding.
About how the method calls in web development is shared here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.