深入JVM invokedynamic指令

某种程度上讲 invokedynamic指令和MethodHandle机制的作用是一样的,都是为了解决分派机制固化在虚拟机的特点,让用户有更高的自由度是其设计的目的。MethodHandle类似,只不过methodHandle采用Java语言和API进行实现,invokedynamic则是字节码来完成。

每一个含有invokedynamic指令的位置称为动态调用点dynamic Call site 这条指令的第一个参数不再是代表方法的符号引用,而是引入了新的常量,从这个常量可以获取的信息:引导方法(Bootstrap Method),此方法存放在新增的BootstrapMethods属性中,方法类型,和名称。引导方法是固有的参数,返回值是java.lang.invoke Callsite对象,这个代表真正执行的目标方法调用,虚拟机根据相关信息找到并执行引导方法,从而获得Call site对象,最终调用需要执行的目标方法

——方法分派规则

invokedynamic指令与其它4条invoke*指令的最大差别是它的分派逻辑不再由虚拟机决定,而是由程序员控制。

传统多层继承的问题:

class GrandFather
{
	void think()
	{
		System.out.println("GrandFather");
	}
}
class Father extends GrandFather
{
	void think()
	{
		System.out.println("Father");
	}
}
class son extends Father
{
	void think()
	{
		//这里可以通过supre.think()调用直接父类Father的think方法
		//但却不能调用到最终父类的GrandFather的think方法
	}
}

son中调用不到GrandFather的think方法 因为无法获取到GrandFather的对象引用 ,而invokevirtual指令分派逻辑是按照方法接收者实际类型分派,这个逻辑受虚拟机控制,难以解决

——使用MethodHandle解决

class son extends Father
{
	void think()
	{
		try
		{
			MethodType mt=MethodType.methodType(void.class);//返回值是void
			//调用findup().findSpecial查找方法 参数列表   从哪儿找  方法名  返回类型
			MethodHandle mh=MethodHandles.lookup().findSpecial(GrandFather.class, "think", mt, getClass());
			mh.invoke(this);
			
		}catch(Throwable e)
		{
			
		}
	}
}

public class Test {

	public static void main(String[] args) {
		new son().think();

	}

}

直接通过MethodHandle查找到GrandFather的think方法,并invoke执行

猜你喜欢

转载自blog.csdn.net/qq_33369979/article/details/88074668
今日推荐