0
点赞
收藏
分享

微信扫一扫

jvm复习: 动态链接


当发生方法重写时,在字节码层面会有动态的语句,也就是在编译的时候无法确定是调用哪个类的方法。

package cn.edu.tju.controller;


class Vehicle {
    public void run(){
        System.out.println("vehicle runs...");
    }
}

class Car extends Vehicle{
    @Override
    public void run(){
        System.out.println("car runs...");
    }
}

class Plane extends Vehicle{
    @Override
    public void run(){
        System.out.println("plane runs...");
    }
}

public class VehicleTest {
    public static void main(String[] args) {
        Vehicle v1 = new Car();
        Vehicle v2 = new Plane();

        v1.run();
        v2.run();
    }
}

生成的字节码:

D:\springcloudskywalking\module1\target\classes\cn\edu\tju\controller>javap -verbose VehicleTest.class
Classfile /D:/springcloudskywalking/module1/target/classes/cn/edu/tju/controller/VehicleTest.class
  Last modified 2023-4-3; size 649 bytes
  MD5 checksum 2869f68f561f1b5b76cf81df2723f3a8
  Compiled from "VehicleTest.java"
public class cn.edu.tju.controller.VehicleTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #8.#25         // java/lang/Object."<init>":()V
   #2 = Class              #26            // cn/edu/tju/controller/Car
   #3 = Methodref          #2.#25         // cn/edu/tju/controller/Car."<init>":()V
   #4 = Class              #27            // cn/edu/tju/controller/Plane
   #5 = Methodref          #4.#25         // cn/edu/tju/controller/Plane."<init>":()V
   #6 = Methodref          #28.#29        // cn/edu/tju/controller/Vehicle.run:()V
   #7 = Class              #30            // cn/edu/tju/controller/VehicleTest
   #8 = Class              #31            // java/lang/Object
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               Lcn/edu/tju/controller/VehicleTest;
  #16 = Utf8               main
  #17 = Utf8               ([Ljava/lang/String;)V
  #18 = Utf8               args
  #19 = Utf8               [Ljava/lang/String;
  #20 = Utf8               v1
  #21 = Utf8               Lcn/edu/tju/controller/Vehicle;
  #22 = Utf8               v2
  #23 = Utf8               SourceFile
  #24 = Utf8               VehicleTest.java
  #25 = NameAndType        #9:#10         // "<init>":()V
  #26 = Utf8               cn/edu/tju/controller/Car
  #27 = Utf8               cn/edu/tju/controller/Plane
  #28 = Class              #32            // cn/edu/tju/controller/Vehicle
  #29 = NameAndType        #33:#10        // run:()V
  #30 = Utf8               cn/edu/tju/controller/VehicleTest
  #31 = Utf8               java/lang/Object
  #32 = Utf8               cn/edu/tju/controller/Vehicle
  #33 = Utf8               run
{
  public cn.edu.tju.controller.VehicleTest();
    descriptor: ()V
    flags: 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 24: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcn/edu/tju/controller/VehicleTest;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #2                  // class cn/edu/tju/controller/Car
         3: dup
         4: invokespecial #3                  // Method cn/edu/tju/controller/Car."<init>":()V
         7: astore_1
         8: new           #4                  // class cn/edu/tju/controller/Plane
        11: dup
        12: invokespecial #5                  // Method cn/edu/tju/controller/Plane."<init>":()V
        15: astore_2
        16: aload_1
        17: invokevirtual #6                  // Method cn/edu/tju/controller/Vehicle.run:()V
        20: aload_2
        21: invokevirtual #6                  // Method cn/edu/tju/controller/Vehicle.run:()V
        24: return
      LineNumberTable:
        line 26: 0
        line 27: 8
        line 29: 16
        line 30: 20
        line 31: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  args   [Ljava/lang/String;
            8      17     1    v1   Lcn/edu/tju/controller/Vehicle;
           16       9     2    v2   Lcn/edu/tju/controller/Vehicle;
}
SourceFile: "VehicleTest.java"

其中第17行
17: invokevirtual #6 // Method cn/edu/tju/controller/Vehicle.run:()V
和第21行
21: invokevirtual #6 // Method cn/edu/tju/controller/Vehicle.run:()V
分别显示调用了Vehicle.run,而真正要调用哪个run方法,在编译成字节码的时候是无法确定的,只有当实际运行时才能确定


举报

相关推荐

0 条评论