方法调用的字节码指令:
字节码指令 | 作用 |
---|---|
invokestatic |
调用静态方法 |
invokespecial |
调用私有实例方法、构造器及 super 关键字等 |
invokevirtual |
调用非私有实例方法,比如 public 和 protected |
invokeinterface |
和上面这条指令类似,不过作用于接口类 |
invokedynamic |
调用动态方法 |
在编译期就确定了具体的调用版本,这个版本在运行时是不可变的。
invokestatic
静态方法invokespecial
私有实例方法、实例构造器和父类方法final
修饰的 invokevirtual
方法:非私有实例方法 public
和 protected
方法在运行时是可变的。很多时候,JVM 需要根据调用者的动态类型,来确定调用的目标方法,这就是动态绑定的过程;相对比,invokestatic
指令加上 invokespecial
指令,就属于静态绑定过程。
final
修饰的invokevirtual
方法invokeinterface
,和上面这条指令类似,不过作用于接口类invokevirtual
指令的多态查找的机制:
java.lang.IllegalAccessError
java.lang.AbstractMethodError
异常,这就是 Java 语言中方法重写的本质。invokevirtual
可以在方法调用的时候(运行时期)知道方法的符号引用转换。部分符号引用在运行期间转化为直接引用,这种转化就是动态链接(虚拟机栈中的动态链接)
使用虚方法表索引来替代元数据查找以提高性能。在实现上,最常用的手段就是为类在方法区中建立一个虚方法表。虚方法表中存放着各个方法的实际入口地址。如果某个方法在子类中没有被重写,那子类的虚方法表里面的地址入口和父类相同方法的地址入口是一致的,都指向父类的实现入口。如果子类中重写了这个方法,子类方法表中的地址将会替换为指向子类实现版本的入口地址。
JVM 编译的时候使用 invokedynamic
实现 Lambda 表达式,invokedynamic
是使用 MethodHandle
实现的,所以 JVM 会根据你编写的 Lambda 表达式的代码,编译出一套可以去调用 MethodHandle
的字节码代码
invokedynamic
这个字节码是比较复杂。和反射类似,它用于一些动态的调用场景,但它和反射有着本质的不同,效率也比反射要高得多。
BootstrapMethods
属性在 Java 1.7 以后才有,位于类文件的属性列表中,这个属性用于保存 invokedynamic
指令引用的引导方法限定符。
和上面介绍的四个指令不同,invokedynamic
并没有确切的接受对象,取而代之的,是一个叫 CallSite
的对象。
invokedynamic
指令的底层,是使用方法句柄(MethodHandle
)来实现的。方法句柄是一个能够被执行的引用,它可以指向静态方法和实例方法,以及虚构的 get
和 set
方法。
句柄类型(MethodType
)是我们对方法的具体描述,配合方法名称,能够定位到一类函数。访问方法句柄和调用原来的指令基本一致,但它的调用异常,包括一些权限检查,在运行时才能被发现。
MethodHandle
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(String.class);
MethodHandles methodHandle = lookup.findVirtual(o.getClass(),"methodName", methodType);
// 往往 invoke 使用比 invokeExact 要多,因为 invokeExact 如果类型不匹配,则会抛错
Object res = methodHandle,invoke(o);
MethodType
表示一个方法类型的对象,每个 MethodHandle
都有一个 MethodType
实例,MethodType
用来指明方法的返回类型和参数类型。其有多个工厂方法的重载。
MethodHandle.Lookup
可以通过相应的 findxxx
方法得到相应的 MethodHandle
,相当于MethodHandle
的工厂方法。查找对象上的工厂方法对应于方法、构造函数和字段的所有主要用例。
findStatic
相当于得到的是一个static
方法的句柄(类似于 invokestatic
的作用),findVirtual
找的是普通方法(类似于 invokevirtual
的作用)
原文:https://www.cnblogs.com/xch-jiang/p/14622288.html