Develop with pleasure!

福岡でCloudとかBlockchainとか。

リフレクションを使わずにMethodHandleを使って動的にメソッドを実行してみる。

Java7からJVM上で動作する動的言語のためにInvoke Dynamicという仕組みが導入された。

Invoke Dynamicの導入前までは、動的言語の特性から静的に型が判断できない実行処理においては、各言語毎に処理系が必要で、その処理系に実行処理が委譲されていた。これがInvoke Dynamicの導入によりJVM側で関数ポインタを切り替えて処理が行えるようになり、各言語毎の処理系に処理を委譲せずともJVMで処理が完結するようになった。そのため、JITによる最適化の恩恵をフルに受けれるようになり、JVM上で動作する動的言語のパフォーマンスが向上するみたい。

で、そんなInvoke Dynamicだけど、動的言語以外にJava自体にも恩恵があり、リフレクションを使って動的に処理を実行している箇所は、リフレクションではなくMethodHandleを使用してInvoke Dynamic命令を実行した方がリフレクションのオーバーヘッドが必要なくなり、パフォーマンスが向上するみたい。
詳しくは→、JDK 7の新機能:Java仮想マシンにおける動的型付け言語のサポート

具体的にどう実装するかというと

public class Hello {

    public void say(String arg) {
        System.out.println("Hello, " + arg);
    }

}


なクラスがあったとして、これをリフレクション使って呼び出すと

Method method = Hello.class.getMethod("say", String.class);
method.invoke(new Hello(), "hoge");


MethodHandle使って呼び出すと

MethodType mt = MethodType.methodType(void.class, String.class);
MethodHandle mh = MethodHandles.lookup().findVirtual(Hello.class, "say", mt);
mh.invokeExact(new Hello(), "fuge");


な実装になる。

パフォーマンス考慮するとJava7以上という制約があっても問題無ければ、リフレクションを使うのではなくMethodHandleを使用した方がよさげか。

追記

と書いたものの、どうも↑だけだと普通にリフレクションの方が速いみたいですね。
Indyが早くないので、教えてください! - 谷本 心 in せろ部屋