深机笔记

来源:互联网 发布:传奇霸业时装分解数据 编辑:程序博客网 时间:2024/05/21 19:28
《深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)》8.3.3节

动态类型语言关键特征是,类型检查主体过程是在运行期而不是编译期
JDK1.7实现JSR-292,新加入java.lang.invoke包,该包主要目的是在依靠符号引用确定目标方法以外,提供一种新的动态确定目标方法的机制,称MethodHandle
拥有MethodHandle后,Java语言拥有类似函数指针或委托的方法别名的工具
在Java语言角度,MethodHandle使用方法和效果与Reflection有相似之处,但它们有以下区别:
1)
从本质上讲,Reflection和MethodHandle机制都在模拟方法调用,但Reflection是在模拟Java代码层次的方法调用,而MethodHandle是在模拟字节码层次的方法调用
MethodHandles.lookup中的3个方法,findStatic()、findVirtual()、findSpecial(),对应invokestatic、invokevirtual&invokeinterface和invokespecial指令的执行权限校验行为,这些底层细节在使用ReflectionAPI时不需关心
2)
Reflection中的java.lang.reflect.Method对象远比MethodHandle中的java.lang.invoke.MethodHandle对象包含的信息多
前者是方法在Java端的全面映像,包含方法的签名、描述符及方法属性表中各种属性的Java端表示方式,还包含执行权限等运行期信息
后者仅仅包含与执行该方法相关的信息
通俗的讲,Reflection是重量级,而MethodHandle是轻量级
3)
MethodHandle是对字节码方法指令调用的模拟,故理论上虚拟机在这方面做的各种优化(如方法内联),在MethodHandle上也应当可以采用类似思路去支持(但目前实现还不完善)
而通过反射去调用方法则不行
4)
MethodHandle与Reflection除上面列举的区别外,最关键的一点还在于去掉前面讨论施加的前提“仅站在Java语言的角度来看”:ReflectionAPI的设计目标是只为Java语言服务,而MethodHandle则设计成可服务所有Java虚拟机上的语言,其中包括Java语言

含有invokedynamic指令的位置称“动态调用点”(Dynamic Call Site)
该指令的第一个参数不再是代表方法符号引用的CONSTANT_Methodref_info常量,而是JDK1.7新加入的CONSTANT_InvokeDynamic_info常量
从该新常量可得到3项信息:引导方法(BootstrapMethod,此方法存放在新增的BootstrapMethods属性中)、方法类型(MethodType)和名称
invokedynamic指令与其他4条"invoke*"指令的最大差别是,它的分派逻辑不由虚拟机决定,而由程序员决定

/** * 使用MethodHandle解决问题 */public class TestMethodHandle {    class GrandFather {        void thinking() {            System.out.println(" i am grandfather");        }    }    class Father extends GrandFather {        void thinking() {            System.out.println(" i am father");        }    }    class Son extends Father {        void thinking() {            try {                MethodType mt = MethodType.methodType(void.class);                MethodHandle mh = lookup().findSpecial(GrandFather.class, " thinking", mt, getClass());                mh.invoke(this);            } catch (Throwable e) {            }        }    }    public static void main(String[] args) {        (new Test().new Son()).thinking();    }}

原创粉丝点击