JVM学习笔记15 方法执行

bilibili-JVM学习笔记15 方法执行
The Java Virtual Machine Specification - Java SE 8 Edition

JVM学习笔记11 - Java字节码初识
JVM学习笔记12 - 解读笔记11中的attributes
JVM学习笔记13
JVM学习笔记14 异常

栈帧 stack frame

  • 栈帧是一种用于帮助虚拟机执行方法调用与方法执行的数据结构
    • 方法的局部变量表
    • 动态链接信息
      • 符号引用
      • 直接引用
    • 方法的返回地址
    • 操作数栈
  • 一个栈帧只会归属于某一个线程,所以不存在并发
    • 一个线程可能有多个栈帧
  • 局部变量表
  • solt
  • 静态解析
    • 有些符号引用是在类加载阶段或是第一次使用时就会转换成为直接引用
      1. 静态方法
      1. 父类方法
      1. 构造方法
      1. 私有方法
    • 以上方法称为非虚方法,在类加载阶段就可以将符号引用转换为直接引用
  • 动态链接
    • 另一些符号引用则是在每次运行期都会转换为直接引用,这体现为 java 的多态性

invoke 指令

  • invokeinterface : 调用接口中的方法,实际上是在运行期决定的,决定到底调用实现该接口的哪个对象的特点方法;
  • invokestatic : 调用静态方法
  • invokespecial :
    • 调用自己的私有方法
    • 调用自己的构造方法
    • 调用父类的方法(实例方法或构造方法)
  • invokevirtual : 调用虚方法(多态),运行期动态查找的过程
  • invokedynamic : jdk1.7 对动态语言的支持

public class InvokeTest1 {
    public static void test() {
        System.out.println("static");
    }

    public static void main(String[] args) {
        test();
    }
}
  public new_package.jvm.p51.InvokeTest1();
    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 8: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lnew_package/jvm/p51/InvokeTest1;

  public static void test();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String static
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 10: 0
        line 11: 8

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

方法重载

package new_package.jvm.p51;

public class InvokeTest2 {

    public void test(Gradepa gradepa) {
        System.out.println("gradepa");
    }

    public void test(Father gradepa) {
        System.out.println("Fathet");
    }

    public void test(Son gradepa) {
        System.out.println("Son");
    }

    public static void main(String[] args) {
        Gradepa gradepa1 = new Father();
        Gradepa gradepa2 = new Son();

        InvokeTest2 main = new InvokeTest2();
        main.test(gradepa1);
        main.test(gradepa2);
    }

}

class Gradepa {
}

class Father extends Gradepa {
}

class Son extends Father {
}

// gradepa
// gradepa
  • 方法的静态分派
    • Gradepa gradepa1 = new Father();
    • gradepa1 的静态类型是 Gradepa ,gradepa1 的实际类型(真正指向的类型)是 Father
    • 变量的静态类型是不会发生变化的,而变量的实际类型则是可以发生变化的(多态的一种体现),实际类型是在运行期方可确定。
  • 方法重载,是一种静态行为
  • 方法重写,动态行为

方法重写 (p53)

  • 动态分派
    • invokevirtual 指令的多态查找流程
        1. 找到操作数栈顶的第一个引用的实际类型
        1. 寻找实际类型是否存在与调用类匹配的方法描述符,若存在且访问权限校验通过,则返回实际类型的该方法的直接引用
        1. 若不存在,则按继承顺序从下往上一次查找,查找到则调用
        1. 若一直查找不到,则抛出异常
    • 方法接收者:方法实际是由哪个对象调用的
package new_package.jvm.p51;

public class StackFrameTest1 {

    public static void main(String[] args) {

        Animal dog = new Dag();
        Animal cat = new Cat();

        dog.sleep();
        cat.sleep();

        dog = new Cat();
        dog.sleep();
    }
}

class Animal {
    public void sleep() {
        System.out.println("Animal is sleep");
    }
}

class Dag extends Animal {
    @Override
    public void sleep() {
        System.out.println("Dag is sleep");
    }
}

class Cat extends Animal {
    @Override
    public void sleep() {
        System.out.println("Cat is sleep");
    }
}
  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 new_package/jvm/p51/Dag
         3: dup
         4: invokespecial #3                  // Method new_package/jvm/p51/Dag."<init>":()V
         7: astore_1
         8: new           #4                  // class new_package/jvm/p51/Cat
        11: dup
        12: invokespecial #5                  // Method new_package/jvm/p51/Cat."<init>":()V
        15: astore_2
        16: aload_1
        17: invokevirtual #6                  // Method new_package/jvm/p51/Animal.sleep:()V
        20: aload_2
        21: invokevirtual #6                  // Method new_package/jvm/p51/Animal.sleep:()V
        24: new           #4                  // class new_package/jvm/p51/Cat
        27: dup
        28: invokespecial #5                  // Method new_package/jvm/p51/Cat."<init>":()V
        31: astore_1
        32: aload_1
        33: invokevirtual #6                  // Method new_package/jvm/p51/Animal.sleep:()V
        36: return
      LineNumberTable:
        line 7: 0
        line 8: 8
        line 10: 16
        line 11: 20
        line 13: 24
        line 14: 32
        line 15: 36
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      37     0  args   [Ljava/lang/String;
            8      29     1   dog   Lnew_package/jvm/p51/Animal;
           16      21     2   cat   Lnew_package/jvm/p51/Animal;

重载与重写的对比

  • 方法重载,是一种静态行为,编译器就可以完全确定;
  • 方法重写是动态的,是运行期行为;

virtual method table

  • 针对方法调用动态分配的过程,虚拟机会在类的方法区建立一个虚方法表的数据结构(virtual method table, vtable);
  • 针对 invokeinterface 指令来说,虚拟机会建立一个接口方法表的数据结构(interface method table, itable);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值