20.JVM栈帧的内部结构-动态链接(Dynamic Linking)

 

1.动态链接(指向运行时常量池的方法引用)

1.动态链接又称为指向运行时常量池的方法引用
2.一个方法对应一个栈帧。每一个栈帧中都包含一个指向运行时常量池中该栈帧所属方法的引用。
3.Java源文件被编译到字节码文件中时,所有的变量方法引用都作为符号引用(Symbolic Reference)保存在class文件的常量池里。例如:描述一个方法调用了另外其他的方法时,就是通过常量池中指向方法的符号引用来表示的,动态链接的作用是为了将这些符号引用转换为调用方法的直接引用。
在这里插入图片描述
如下图所示,每一个线程都有自己的PC计数器、本地方法栈、虚拟机栈。虚拟机栈中存储的是一个个栈帧,栈帧中包含局部变量表、方法返回地址、操作数栈、动态链接(指向运行时常量池的方法引用)。
图中Constant Pool Reference就是动态链接,指向的是方法区中运行时常量池的方法引用(method reference)。
在这里插入图片描述
例子:

package jvn;
public class DynamicLinkingTest {
    int num = 10;
    public void methodA(){
        System.out.println("methodA()....");
    }
    public void methodB(){
        System.out.println("methodB()....");
        methodA();
        num++;
    }
}

使用javap -v DynamicLinkingTest 反编译上面的java代码产生的class文件。得到下面的字节码输出。
1.其中的Constant pool就是常量池,当程序运行起来的时候,就是运行时常量池。
2.第一列#1,#2等等,这些就是符号引用。
3.methodB调用methodA对应的指令是9: invokevirtual #36 // Method methodA:()V
4.为什么需要常量池?
常量池的作用就是为了提供一些符号和常量,便于指令的识别。

C:\Users\12558>javap -v D:\Eclipse_workspace\JVM\jvn\bin\jvn\DynamicLinkingTest.class
Classfile /D:/Eclipse_workspace/JVM/jvn/bin/jvn/DynamicLinkingTest.class
  Last modified 2020-7-5; size 688 bytes
  MD5 checksum 7c8d5b298eaf82e8891ad1de67e14fbd
  Compiled from "DynamicLinkingTest.java"
public class jvn.DynamicLinkingTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // jvn/DynamicLinkingTest
   #2 = Utf8               jvn/DynamicLinkingTest
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               num
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Methodref          #3.#11         // java/lang/Object."<init>":()V
  #11 = NameAndType        #7:#8          // "<init>":()V
  #12 = Fieldref           #1.#13         // jvn/DynamicLinkingTest.num:I
  #13 = NameAndType        #5:#6          // num:I
  #14 = Utf8               LineNumberTable
  #15 = Utf8               LocalVariableTable
  #16 = Utf8               this
  #17 = Utf8               Ljvn/DynamicLinkingTest;
  #18 = Utf8               methodA
  #19 = Fieldref           #20.#22        // java/lang/System.out:Ljava/io/PrintStream;
  #20 = Class              #21            // java/lang/System
  #21 = Utf8               java/lang/System
  #22 = NameAndType        #23:#24        // out:Ljava/io/PrintStream;
  #23 = Utf8               out
  #24 = Utf8               Ljava/io/PrintStream;
  #25 = String             #26            // methodA()....
  #26 = Utf8               methodA()....
  #27 = Methodref          #28.#30        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #28 = Class              #29            // java/io/PrintStream
  #29 = Utf8               java/io/PrintStream
  #30 = NameAndType        #31:#32        // println:(Ljava/lang/String;)V
  #31 = Utf8               println
  #32 = Utf8               (Ljava/lang/String;)V
  #33 = Utf8               methodB
  #34 = String             #35            // methodB()....
  #35 = Utf8               methodB()....
  #36 = Methodref          #1.#37         // jvn/DynamicLinkingTest.methodA:()V
  #37 = NameAndType        #18:#8         // methodA:()V
  #38 = Utf8               SourceFile
  #39 = Utf8               DynamicLinkingTest.java
{
  int num;
    descriptor: I
    flags:

  public jvn.DynamicLinkingTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #10                 // Method java/lang/Object."<init>":()V
         4: aload_0
         5: bipush        10
         7: putfield      #12                 // Field num:I
        10: return
      LineNumberTable:
        line 3: 0
        line 5: 4
        line 3: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Ljvn/DynamicLinkingTest;

  public void methodA();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #25                 // String methodA()....
         5: invokevirtual #27                 // Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
         8: return
      LineNumberTable:
        line 8: 0
        line 9: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Ljvn/DynamicLinkingTest;

  public void methodB();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: getstatic     #19                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #34                 // String methodB()....
         5: invokevirtual #27                 // Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
         8: aload_0
         9: invokevirtual #36                 // Method methodA:()V
        12: aload_0
        13: dup
        14: getfield      #12                 // Field num:I
        17: iconst_1
        18: iadd
        19: putfield      #12                 // Field num:I
        22: return
      LineNumberTable:
        line 12: 0
        line 14: 8
        line 16: 12
        line 17: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   Ljvn/DynamicLinkingTest;
}
SourceFile: "DynamicLinkingTest.java"

 

posted @ 2020-11-18 10:46  跃小云  阅读(507)  评论(0编辑  收藏  举报