JVM_03 runtime data area 1_Stack_Dynamic Linking_Dynamic Linking

Dynamic Linking
  • Each stack frame contains a reference to the runtime constant pool or the method to which the stack frame belongs. The purpose of including this reference is to support the dynamic linking of the code of the current method. Such as the invokedynamic instruction
  • When the Java source file is compiled into a bytecode file, all variables and method references are saved as symbolic references (symbolic Refenrence) in the constant pool of the class file. For example, when describing that a method calls another method, it is represented by the symbolic references pointing to the method in the constant pool. Then the function of dynamic linking is to convert these symbolic references into direct references for calling the method.

Insert picture description here
Why do we need a constant pool? The purpose of the
constant pool is to provide some symbols and constants to facilitate the identification of instructions.
Insert picture description here

Insert picture description here

2.5.1 Method call

In the JVM, the conversion of symbolic references to direct references to call methods is related to the binding mechanism of the method

Static link

  • When a bytecode file is loaded into the JVM, if the target method being called is known at compile time and the runtime remains unchanged. In this case, the process of converting the symbolic reference of the calling method into a direct reference is called static linking.

Dynamic link

  • If the called method cannot be determined at compile time, that is to say, the symbolic reference of the calling method can only be converted into a direct reference during the running period of the program. Because this reference conversion process is dynamic, it is also called It is a dynamic link.

The binding mechanism of the corresponding method is: Early Binding and Late Bingding. Binding is a process in which a symbolic reference is replaced by a direct reference of a field, method, or class, and this happens only once.

Early binding

  • Early binding means that if the called target method is known at compile time and the runtime remains unchanged, then this method can be bound to the type to which it belongs. In this way, since it is clear what the called target method is Which one is it, so you can use static linking to convert symbol references to direct references.

Late binding

  • If the method to be called cannot be determined at compile time, only the relevant method can be bound according to the actual type during program runtime. This binding method is also called late binding.

With the emergence of high-level languages, there are more and more object-oriented programming languages ​​similar to java. Although these programming languages ​​have certain differences in grammatical styles, they always maintain a commonality with each other. , That is, they all support object-oriented features such as encapsulation, integration, and polymorphism. Since this type of programming language has polymorphism, it naturally has two binding methods: early binding and late binding.
Any ordinary method in Java actually has the characteristics of virtual functions, which are equivalent to virtual functions in C++ (in C++, the keyword virtual needs to be explicitly defined). If you do not want a method to have the characteristics of a virtual function in a Java program, you can use the keyword final to mark this method.

2.5.2 Virtual method and non-virtual method

The prerequisite for the use of polymorphism of subclass objects: ①class inheritance relationship ②method rewriting

  • Non-virtual method

    • If the method determines the specific calling version in the compiler, this version is immutable at runtime. Non-virtual method
    • Static methods, private methods, final methods, instance constructors, and parent methods are all non-virtual methods
  • Virtual methods

The following method call instructions are provided in the virtual machine:
ordinary call instructions :

  • 1.invokestatic: Invoke a static method, and determine the only method version in the parsing phase;
  • 2. Invokespecial: Invoke methods, private and Frey methods, and determine the only method version in the analysis phase;
  • 3. Invokevirtual calls all virtual methods;
  • 4. Invokeinterface: call the interface method;

Dynamic call instruction:

  • 5. Invokedynamic: dynamically resolve the method to be called, and then execute.

The first four instructions are solidified inside the virtual machine, and the call and execution of the method cannot be interfered by human intervention, while the invokedynamic instruction supports the user to determine the method version. The methods called by the invokestatic instruction and the invokespecial instruction are called non-virtual methods, and the rest (except for the final modification) are called virtual methods.

/**
 * 解析调用中非虚方法、虚方法的测试
 */
class Father {
    public Father(){
        System.out.println("Father默认构造器");
    }

    public static void showStatic(String s){
        System.out.println("Father show static"+s);
    }

    public final void showFinal(){
        System.out.println("Father show final");
    }

    public void showCommon(){
        System.out.println("Father show common");
    }

}

public class Son extends Father{
    public Son(){
        super();
    }

    public Son(int age){
        this();
    }

    public static void main(String[] args) {
        Son son = new Son();
        son.show();
    }

    //不是重写的父类方法,因为静态方法不能被重写
    public static void showStatic(String s){
        System.out.println("Son show static"+s);
    }

    private void showPrivate(String s){
        System.out.println("Son show private"+s);
    }

    public void show(){
        //invokestatic
        showStatic(" 大头儿子");
        //invokestatic
        super.showStatic(" 大头儿子");
        //invokespecial
        showPrivate(" hello!");
        //invokespecial
        super.showCommon();
        //invokevirtual 因为此方法声明有final 不能被子类重写,所以也认为该方法是非虚方法
        showFinal();
        //虚方法如下
        //invokevirtual
        showCommon();//没有显式加super,被认为是虚方法,因为子类可能重写showCommon
        info();

        MethodInterface in = null;
        //invokeinterface  不确定接口实现类是哪一个 需要重写
        in.methodA();

    }

    public void info(){

    }

}

interface MethodInterface {
    void methodA();
}

About the invokedynamic command

  • The JVM bytecode instruction set has been relatively stable. It was not until java7 that an invokedynamic instruction was added. This is an improvement made by Java in order to achieve [dynamic type language] support.
  • However, java7 does not provide a method to directly generate invokedynamic instructions. It is necessary to use ASM, a low-level bytecode tool, to generate invokedynamic instructions. Until the emergence of Java8 Lambda expressions and the generation of invokedynamic instructions, there is no direct generation in java. the way
  • The essence of the dynamic language type support added in Java 7 is the modification of the Java virtual machine specification, rather than the modification of the Java language rules. This is relatively complicated, and the method calls in the virtual machine are increased. The most direct beneficiary It is the compiler of the dynamic language that runs on the java receipt

Dynamically Typed Language and Statically Typed Language

  • The difference between a dynamically typed language and a statically typed language is whether the type is checked at compile time or at runtime. The former is a statically typed language, and the opposite is a dynamically typed language.
  • To put it bluntly, static language is to judge the type information of the variable itself; the dynamic type predictor judges the type information of the variable value. The variable has no type information, and the variable value has type information. This is an important feature of dynamic languages.
  • Java is a statically typed language (although lambda expressions add dynamic features to it), js and python are dynamically typed languages.
动态链接:指向运行时常量池的方法的引用
为了将符号引用转化为调用方法的直接引用
常量池:为了提高一些符号和常量,便于指令的引用

符号的引用到直接的引用与绑定机制有关.动态绑定和静态绑定
编译期间为静态链接,运行期间为动态链接
invokevirtual:方法调用为晚期绑定
invokespecail:构造器为早期绑定

invokespecail,invokestatic编译期课确定的为非虚方法:静态方法,final,私有方法,实例构造器,父类方法
invokevirtual,invokeinterface其他为虚方法
invokedynamic为lambda表达式提供的动态方法,jdk8以后提供的

Guess you like

Origin blog.csdn.net/qq_43141726/article/details/114582094