JVM动态链接的举例说明

全篇链接

java代码

package com.company;

public class Main {

    static int num = 10;
    public static void main(String[] args) {

        methodA();
    }

    public static void methodA(){
        System.out.println("methodA().....");
        methodB();
    }

    public static void methodB(){
        System.out.println("methodB()....");

    }

}

对应.class代码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.company;

public class Main {
    static int num = 10;

    public Main() {
    }

    public static void main(String[] args) {
        methodA();
    }

    public static void methodA() {
        System.out.println("methodA().....");
        methodB();
    }

    public static void methodB() {
        System.out.println("methodB()....");
    }
}

 对应的‘反编译’

javap -v Main.class


  Compiled from "Main.java"
public class com.company.Main
  minor version: 0
  major version: 54
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #9                          // com/company/Main
  super_class: #10                        // java/lang/Object
  interfaces: 0, fields: 1, methods: 5, attributes: 1
Constant pool:
   #1 = Methodref          #10.#29   去#10和#29寻找     // java/lang/Object."<init>":()V(构成器方法,无参)
   #2 = Methodref          #9.#30         // com/company/Main.methodA:()V
   #3 = Fieldref           #31.#32        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = String             #33            // methodA().....
   #5 = Methodref          #34.#35        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Methodref          #9.#36         // com/company/Main.methodB:()V
   #7 = String             #37            // methodB()....
   #8 = Fieldref           #9.#38         // com/company/Main.num:I
   #9 = Class              #39            // com/company/Main
  #10 = Class              #40            // java/lang/Object
  #11 = Utf8               num
  #12 = Utf8               I
  #13 = Utf8               <init>
  #14 = Utf8               ()V
  #15 = Utf8               Code
  #16 = Utf8               LineNumberTable
  #17 = Utf8               LocalVariableTable
  #18 = Utf8               this
  #19 = Utf8               Lcom/company/Main;
  #20 = Utf8               main
  #21 = Utf8               ([Ljava/lang/String;)V
  #22 = Utf8               args
  #23 = Utf8               [Ljava/lang/String;
  #24 = Utf8               methodA
  #25 = Utf8               methodB
  #26 = Utf8               <clinit>
  #27 = Utf8               SourceFile
  #28 = Utf8               Main.java
  #29 = NameAndType        #13:#14        // "<init>":()V
  #30 = NameAndType        #24:#14        // methodA:()V
  #31 = Class              #41            // java/lang/System
  #32 = NameAndType        #42:#43        // out:Ljava/io/PrintStream;
  #33 = Utf8               methodA().....
  #34 = Class              #44            // java/io/PrintStream
  #35 = NameAndType        #45:#46        // println:(Ljava/lang/String;)V
  #36 = NameAndType        #25:#14        // methodB:()V
  #37 = Utf8               methodB()....
  #38 = NameAndType        #11:#12        // num:I
  #39 = Utf8               com/company/Main
  #40 = Utf8               java/lang/Object
  #41 = Utf8               java/lang/System
  #42 = Utf8               out
  #43 = Utf8               Ljava/io/PrintStream;
  #44 = Utf8               java/io/PrintStream
  #45 = Utf8               println
  #46 = Utf8               (Ljava/lang/String;)V
{
  static int num;
    descriptor: I
    flags: (0x0008) ACC_STATIC

  public com.company.Main();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1    (向常量池中寻找)              // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/company/Main;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=1, args_size=1
         0: invokestatic  #2                  // Method methodA:()V
         3: return
      LineNumberTable:
        line 8: 0
        line 9: 3
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       4     0  args   [Ljava/lang/String;

  public static void methodA();
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #3    (向常量池中寻找)              // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #4                  // String methodA().....
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V

         8: invokestatic  #6                  // Method methodB:()V
        11: return
      LineNumberTable:
        line 12: 0
        line 13: 8
        line 14: 11

  public static void methodB();
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #7                  // String methodB()....
         5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V

         8: return
      LineNumberTable:
        line 17: 0
        line 19: 8

  static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        10
         2: putstatic     #8                  // Field num:I
         5: return
      LineNumberTable:
        line 5: 0
}
SourceFile: "Main.java"
 

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

  • 每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用。 包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接( Dynamic Linking)。比如: invokedynamic指令
  • 在Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用( symbolic Reference)保存在class文件的常量池里。 比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值