java - 如何在 JDK 6 中使用方法句柄?

标签 java reflection java-6 methodhandle

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

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

经过一番研究,我发现了静态 final方法句柄:

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 编译类,因为 JDK 6 不理解 @PolymorphicSignature 注释;方法句柄的编译方式与使用合成签名的其他方法略有不同。

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

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

关于java - 如何在 JDK 6 中使用方法句柄?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29907401/

相关文章:

java - Camel 使用额外参数连接到 RabbitMQ 队列

JavaFX 排序列表 : listen the list changes and the list items updated event

Array.SetValue 在运行时的 C# 类型转换

Java 6 支持的 Unicode 版本

Java - 非匿名比较器模拟从集合中选择元素

java - 如何处理大于 Float.MAX_VALUE 的浮点值输入

java.beans.PropertyEditorManager.findEditor(Locale.class) 在 spring 中返回 null

java - 如何使用 m2eclipse 将 Maven Artifact 部署到私有(private) github 存储库或从私有(private) github 存储库解析 Maven Artifact ?

java - 如何将动态加载的注释类转换为Annotation?

java - 如何使用 JUnit 反射测试实体注释