如何使用 JDK 6 的方法句柄?

How can I use method handles with JDK 6?

这里的情况很奇怪。我需要多次调用相同的 class 实例方法(1000/秒范围),但无法导入或构建所需的库。我正在尝试在我的 JEE 项目中调用一个方法,该方法使用应用程序服务器提供的库中的 class。 JEE 项目仍然需要 运行 在其他应用程序服务器上,所以我不能简单地针对该库进行构建。反思是我认为唯一的解决办法。

执行速度如此之快时,使用反射的执行时间比直接调用慢几个数量级。

经过一些研究,我发现了 static final MethodHandles:

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;



public class Test {

    static final MethodHandle sfmh;

    static {
        MethodHandle mh = null;
        try {
            final Class<?> clazz = Class.forName("com.me.lib");
            Method m = clazz.getMethod("MyMethod");
            mh = MethodHandles.lookup().unreflect(m);
        } catch (Throwable e) {
            mh = null;
        }

        sfmh = mh;
    }

    public static void main(String[] args) throws Throwable {
        int i = 0;
        System.out.println("starting");
        long start = System.currentTimeMillis();
        for(i = 0; i < 1000000000; i++) {
            sfmh.invokeExact();
        }
        long total = System.currentTimeMillis() - start;
        System.out.println("Time: " + total + " milliseconds");
    }

}

效果很好,让我获得了可接受的速度结果(慢 2-4 倍,而不是慢 200 倍)。这个完美的解决方案似乎有一个问题——我需要在 Java 6 上 运行(嘘,嘶嘶声,这是一个要求)

针对 1.6 进行编译时,我得到:

Invocation of polymorphic methods not allowed for source level below 1.7

上线

sfmh.invokeExact();

是否有任何解决方案可以利用适用于 1.6 的 MethodHandle 概念?

不,方法句柄仅在 JDK 7 中添加,在此之前无法访问。您也不能针对方法句柄 API 编译 class,因为 JDK 6 不理解 @PolymorphicSignature 注释;方法句柄的编译方式与使用合成签名的其他方法略有不同。

除此之外,反射在现代 JVM 上并不慢,也许 运行 您的应用程序在最近的 JVM 上运行?在 JVM v8 上 运行 Java 6 代码完全没问题。最后,由于多种原因,您的基准测试存在缺陷。也许您的反射代码即使在今天也不慢? JVM 知道一个称为 inflation 的概念,它避免了 JNI 调用的性能开销。

以下是在 v8 JVM 上使用 harness 的一些结果,比较了反射、公共调用和方法句柄:https://gist.github.com/raphw/881e1745996f9d314ab0