“栈帧内部包含一个指向运行时常量池中该栈帧所属方法的引用,该引用的目的支持动态代理”
1.方法区中字节码已经有直接引用为什么还要在栈帧里放?
Child类继承Father类,并重写doSomething方法:
在静态解析时候,看到变量father和child的静态类型都是Father,所以,doSomething方法都解析成Father类里的方法。而child变量的实际类型是Child,应该调用Child类里的doSomething方法,因此方法区里静态解析式不完全正确,要在运行期间栈帧进栈的时候动态连接到真实的类和方法。
2. 已经创建了栈帧,还存一个指向自己的地址多余吗?
动态连接发生在栈帧完全入栈之前,也在局部变量表等形成之前。
以Test类最后一条语句child.doSomething为例。执行到该条语句之时,找到doSomething的直接引用,即在方法区里的地址。形成了指向Child类doSomething方法的动态连接,找到了该方法的入口,也就找到了对应得字节码指令,有了局部变量表和操作数栈的出入栈,然后形成了doSomething这个方法的栈帧。字节码指令指行完后,doSomething方法的栈帧出栈,根据返回地址,返回到test方法继续执行。
动态连接是找到正确方法的入口,然后才有后来的进栈出栈的执行。
3. 静态多分派
由1中的例子可知,编译期是根据对象声明的类型来选择方法。调用过程中首先确定调用者的静态类型是什么,即child的静态类型Father,然后根据要调用的方法参数的静态类型(声明类型)确定所有重载方法中要调用哪一个(方法重载)。两者共同决定所以是多分派。