方法调用
在程序运行时,进行方法调用是最普遍,最频繁的操作
方法调用不等于方法执行:
方法调用阶段唯一的任务就是确定被调用的方法版本,即调用哪一个方法
不涉及方法内部的具体运行过程
Class文件的编译过程不包括传统编译中的连接步骤...invokevirtual指令运行时解析过程大致分为以下几个步骤:
找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C
如果在类型C中找到与常量中的描述符和简单名称相符合的方法,然后进行访问权限验证...,而且动态分派的方法版本选择过程需要运行时在类的方法元数据中搜索合适的目标方法
因此在虚拟机的实际实现中,为了基于性能的考虑,大部分实现都不会真正的进行如此频繁的搜索
最常用的"稳定优化"的方式是为类在方法区中建立一个虚方法表...,都指向父类的实际入口
如果子类中重写了这个方法,子类方法表中的地址将会替换为指向子类实际方法的入口地址
具有相同签名的方法,在父类,子类的虚方法表中具有一样的索引序号:
这样当类型变换时,仅仅需要变更查找的方法表...,就可以从不同的虚方法表中按索引转换出所需要的入口地址
方法表一般在类加载阶段的连接阶段进行初始化:
准备了类的变量初始值后,虚拟机会把该类的方法表也初始化完毕