JDK7从虚拟机级别添加了invokedynamic 命令,意图最大程度的支持动态语言调用。
函数句柄可以理解成C++的函数指针,执行的时候没有Method反射的虚拟机自检,所以理论效率会比传统反射高,测试代码如下:
package common;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
public class TestMain {
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
Foo instance = new Foo();
//搜索函数句柄
MethodType methodType = MethodType.methodType(void.class);
MethodHandle methodHandle = lookup.findVirtual(Foo.class, "doSomething", methodType);
methodHandle.invoke(instance);
//解除反射检测,使用invokedynamic命令直接执行
Method method = Foo.class.getDeclaredMethod("doSomething");
methodHandle = lookup.unreflect(method);
int testTimes = 9999999;
long t1 = System.currentTimeMillis();
for(int i=0;i<testTimes;i++){
methodHandle.invokeExact(instance);
}
long t2 = System.currentTimeMillis();
System.out.println("句柄调用:"+(t2-t1));
t1 = System.currentTimeMillis();
for(int i=0;i<testTimes;i++){
method.invoke(instance);
}
t2 = System.currentTimeMillis();
System.out.println("反射调用:"+(t2-t1));
t1 = System.currentTimeMillis();
for(int i=0;i<testTimes;i++){
instance.doSomething();
}
t2 = System.currentTimeMillis();
System.out.println("直接调用:"+(t2-t1));
}
}
每种方式执行9999999次,实际运行耗时如下
句柄调用:107ms
反射调用:69ms
直接调用:3ms
实际执行效率句柄调用比反射慢,可能是JDK7刚刚实现函数句柄,还未优化导致,而反射已经过多个版本的优化,期望在JDK1.8+里能够得到优异的表现