一、说明
  • 1.指向运行时常量池的方法引用
  • 2.每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用
  • 3.包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)
  • 4.在java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(Symbolic Reference)保存在class文件的常量池里。比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的
  • 5.动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用
二、代码示例
package com.learning.stack.dynamic_linking;

/**
 * @Author wangyouhui
 * @Description 动态链接
 **/
public class DynamicLinkingTest {
    int num = 10;

    public void methodOne(){
        System.out.println("方法1执行了");
        methodTwo();
        num++;
    }

    public void methodTwo(){
        System.out.println("方法2执行了");
    }
}
三、生成的字节码
Classfile /F:/jdk-learning/jvm/target/classes/com/learning/stack/dynamic_linking/DynamicLinkingTest.class
  Last modified 2023-10-28; size 756 bytes
  MD5 checksum 96b3029ecd8f2d56b0fc46825936f83b
  Compiled from "DynamicLinkingTest.java"
public class com.learning.stack.dynamic_linking.DynamicLinkingTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #9.#23         // java/lang/Object."<init>":()V
   #2 = Fieldref           #8.#24         // com/learning/stack/dynamic_linking/DynamicLinkingTest.num:I
   #3 = Fieldref           #25.#26        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = String             #27            // 方法1执行了
   #5 = Methodref          #28.#29        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Methodref          #8.#30         // com/learning/stack/dynamic_linking/DynamicLinkingTest.methodTwo:()V
   #7 = String             #31            // 方法2执行了
   #8 = Class              #32            // com/learning/stack/dynamic_linking/DynamicLinkingTest
   #9 = Class              #33            // java/lang/Object
  #10 = Utf8               num
  #11 = Utf8               I
  #12 = Utf8               <init>
  #13 = Utf8               ()V
  #14 = Utf8               Code
  #15 = Utf8               LineNumberTable
  #16 = Utf8               LocalVariableTable
  #17 = Utf8               this
  #18 = Utf8               Lcom/learning/stack/dynamic_linking/DynamicLinkingTest;
  #19 = Utf8               methodOne
  #20 = Utf8               methodTwo
  #21 = Utf8               SourceFile
  #22 = Utf8               DynamicLinkingTest.java
  #23 = NameAndType        #12:#13        // "<init>":()V
  #24 = NameAndType        #10:#11        // num:I
  #25 = Class              #34            // java/lang/System
  #26 = NameAndType        #35:#36        // out:Ljava/io/PrintStream;
  #27 = Utf8               方法1执行了
  #28 = Class              #37            // java/io/PrintStream
  #29 = NameAndType        #38:#39        // println:(Ljava/lang/String;)V
  #30 = NameAndType        #20:#13        // methodTwo:()V
  #31 = Utf8               方法2执行了
  #32 = Utf8               com/learning/stack/dynamic_linking/DynamicLinkingTest
  #33 = Utf8               java/lang/Object
  #34 = Utf8               java/lang/System
  #35 = Utf8               out
  #36 = Utf8               Ljava/io/PrintStream;
  #37 = Utf8               java/io/PrintStream
  #38 = Utf8               println
  #39 = Utf8               (Ljava/lang/String;)V
{
  int num;
    descriptor: I
    flags:

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

  public void methodOne();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #4                  // String 方法1执行了
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: aload_0
         9: invokevirtual #6                  // Method methodTwo:()V
        12: aload_0
        13: dup
        14: getfield      #2                  // Field num:I
        17: iconst_1
        18: iadd
        19: putfield      #2                  // Field num:I
        22: return
      LineNumberTable:
        line 11: 0
        line 12: 8
        line 13: 12
        line 14: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   Lcom/learning/stack/dynamic_linking/DynamicLinkingTest;

  public void methodTwo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #7                  // String 方法2执行了
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 17: 0
        line 18: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Lcom/learning/stack/dynamic_linking/DynamicLinkingTest;
}
SourceFile: "DynamicLinkingTest.java"
四、字节码说明
4.1 常量池
Constant pool:
   #1 = Methodref          #9.#23         // java/lang/Object."<init>":()V
   #2 = Fieldref           #8.#24         // com/learning/stack/dynamic_linking/DynamicLinkingTest.num:I
   #3 = Fieldref           #25.#26        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = String             #27            // 方法1执行了
   #5 = Methodref          #28.#29        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Methodref          #8.#30         // com/learning/stack/dynamic_linking/DynamicLinkingTest.methodTwo:()V
   #7 = String             #31            // 方法2执行了
   #8 = Class              #32            // com/learning/stack/dynamic_linking/DynamicLinkingTest
   #9 = Class              #33            // java/lang/Object
  #10 = Utf8               num
  #11 = Utf8               I
  #12 = Utf8               <init>
  #13 = Utf8               ()V
  #14 = Utf8               Code
  #15 = Utf8               LineNumberTable
  #16 = Utf8               LocalVariableTable
  #17 = Utf8               this
  #18 = Utf8               Lcom/learning/stack/dynamic_linking/DynamicLinkingTest;
  #19 = Utf8               methodOne
  #20 = Utf8               methodTwo
  #21 = Utf8               SourceFile
  #22 = Utf8               DynamicLinkingTest.java
  #23 = NameAndType        #12:#13        // "<init>":()V
  #24 = NameAndType        #10:#11        // num:I
  #25 = Class              #34            // java/lang/System
  #26 = NameAndType        #35:#36        // out:Ljava/io/PrintStream;
  #27 = Utf8               方法1执行了
  #28 = Class              #37            // java/io/PrintStream
  #29 = NameAndType        #38:#39        // println:(Ljava/lang/String;)V
  #30 = NameAndType        #20:#13        // methodTwo:()V
  #31 = Utf8               方法2执行了
  #32 = Utf8               com/learning/stack/dynamic_linking/DynamicLinkingTest
  #33 = Utf8               java/lang/Object
  #34 = Utf8               java/lang/System
  #35 = Utf8               out
  #36 = Utf8               Ljava/io/PrintStream;
  #37 = Utf8               java/io/PrintStream
  #38 = Utf8               println
  #39 = Utf8               (Ljava/lang/String;)V
4.1 方法调用
  • 1.methodOne方法调用methodTwo方法
9: invokevirtual #6                  // Method methodTwo:()V
  • 2.invokevirtual调用虚方法
  • 3. #6表示Methodref方法引用,指向#8.#30
 #6 = Methodref          #8.#30         // com/learning/stack/dynamic_linking/DynamicLinkingTest.methodTwo:()V
  • 4. #8表示Class
   #8 = Class              #32            // com/learning/stack/dynamic_linking/DynamicLinkingTest
  • 5. #32表示类为com/learning/stack/dynamic_linking/DynamicLinkingTest
  #32 = Utf8               com/learning/stack/dynamic_linking/DynamicLinkingTest
  • 6. #30表示名字和返回类型
  #30 = NameAndType        #20:#13        // methodTwo:()V
  • 7. #20表示名字为methodTwo
  #20 = Utf8               methodTwo
  • 8. #13表示返回类型为void
  #13 = Utf8               ()V
4.3 变量
  • 1. int num = 10;
#2 = Fieldref           #8.#24         // com/learning/stack/dynamic_linking/DynamicLinkingTest.num:I
  • 2. 属性引用,指向#8.#24
  • 3. #8表示Class
   #8 = Class              #32            // com/learning/stack/dynamic_linking/DynamicLinkingTest
  • 4. #32表示类为com/learning/stack/dynamic_linking/DynamicLinkingTest
  #32 = Utf8               com/learning/stack/dynamic_linking/DynamicLinkingTest
  • 5. #24表示名字和类型
  #24 = NameAndType        #10:#11        // num:I
  • 6. #10表示属性名字为num
  #10 = Utf8               num
  • 7. #11表示属性的类型int
  #11 = Utf8               I
4.4 字符串
  • 1. #4表示是字符串
   #4 = String             #27            // 方法1执行了
  • 2. #27表示Utf8的字符串"方法1执行了"
  #27 = Utf8               方法1执行了
4.5 父类Object
  • 1. #1表示方法引用
   #1 = Methodref          #9.#23         // java/lang/Object."<init>":()V
  • 2. #9表示类
   #9 = Class              #33            // java/lang/Object
  • 3. #33表示类名为java/lang/Object
  #33 = Utf8               java/lang/Object
4.6 System类
  • 1. #3表示属性引用
   #3 = Fieldref           #25.#26        // java/lang/System.out:Ljava/io/PrintStream;
  • 2. #25表示类
  #25 = Class              #34            // java/lang/System
  • 3. #34表示类名为java/lang/System
  #34 = Utf8               java/lang/System
  • 4. #26表示名称和类型
  #26 = NameAndType        #35:#36        // out:Ljava/io/PrintStream;
  • 5. #35表示名称为out
  #35 = Utf8               out
  • 6. #36表示类型为 Ljava/io/PrintStream
  #36 = Utf8               Ljava/io/PrintStream;
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐