jvm-方法调用

jvm-方法调用

起男 405 2022-11-25

jvm-方法调用

在jvm中,将符号引用转换为调用方法的直接引用与方法的绑定机制相关

  • 静态连接:一个字节码文件被装载进jvm时,如果被调用的目标方法在编译期可知,且运行期保存不变时
  • 动态连接:被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期间将调用方法的符号引用转换为直接引用

对应的绑定机制为:

  • 早期绑定:被调用的目标方法在编译期可知,且运行期间保持不变时,即可将这个方法与所属的类型进行绑定,这样一来就可以使用静态连接的方式将符号引用转换为直接引用
  • 晚期绑定:被调用的方法在被编译期无法确定下来

虚方法和非虚方法:

  • 如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的。这样的方法称为非虚方法
  • 静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法
  • 其他方法称为虚方法

jvm方法调用指令

  • 普通调用指令:

    • invokestatic:调用静态方法,解析阶段确定唯一方法版本
    • invokespecial:调用<init>方法、私有及父类方法,解析阶段确定唯一方法版本
    • invokevirtual:调用所有虚方法,和final方法
    • invokeinterface:调用接口方法
  • 动态调用指令:

    • invokedynamic(jdk7新增):动态解析出需要调用的方法,然后执行

      这是为了实现动态语言而做的一种改进

java7中没用直接提供invokedynamic指令的方法,需要借助于asm

直到java8的lamobda表达式的出现,invokedynamic指令才能直接生成

方法重写的本质

  1. 找到操作数栈顶的第一个元素所执行的对象的实际类型,记作c
  2. 如果在类型c中找到与常量中的描述符合简单名称想符的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束;如果不通过,则返回IllegalAccessError异常
  3. 否则,按照继承关系从下往上依次对c的各个父类进行第二步的搜索和验证过程
  4. 如果始终没用找到合适的方法,则抛出AbstractMethodError异常

IllegalAccessError:程序视图访问或修改一个属性或调用一个方法,这个属性或方法,没有访问权限

虚方法表

在面向对象的编程中,会很频繁的使用到动态分派,如果在每次动态分派的过程中都需要重新在类的方法元数据中搜索合适的目标的话就可能影响到执行效率。因此,为了提高性能,jvm采用在类的方法区建立一个虚方法表,用索引来替代查找

每个类中都有一个虚方法表,表中存放着各个方法的实际入口

虚方法表会在类加载的连接(解析)阶段被创建并被初始化,类的变量初始值准备完成之后,jvm会把该类的方法表也初始化完毕