web-dev-qa-db-ja.com

MethodHandleの方が速いのに、なぜリフレクションを使用してクラスメンバーにアクセスするのですか?

Java 7のリリースに伴い、 MethodHandle が登場しました。これにより、ユーザーは、基になるバイトコードを使用しているかのようにメソッドを呼び出すことができます。 _MethodHandles.Lookup_ クラスは、クラスメンバーにアクセスするためのメソッドハンドルを作成するためのファクトリメソッドを提供します。

Lookupオブジェクトのファクトリメソッドは、メソッド、コンストラクター、およびフィールドのすべての主要なユースケースに対応しています。ファクトリメソッドによって作成された各メソッドハンドルは、特定のバイトコードの動作と機能的に同等です。

機能的には、これはリフレクションを使用してこれらの同じクラスメンバーにアクセスすることとほぼ同等ですが、 メソッドハンドルはリフレクション よりも高速です。

それで、 Field#get(..) / Method.invoke(..) のようなリフレクション機能をまだ使用する理由はありますか、またはこれらのメソッドは導入により事実上廃止されていますか?より高速なメソッドハンドルの?

メソッドハンドルはJava 7で導入されましたが、私の質問は主にJava 8に関係し、直接とほぼ同等のパフォーマンスに達するように最適化されていることに注意してください。フィールド/メソッド呼び出し、リフレクションの能力を超えています。

29
FThompson

リフレクションとメソッドハンドルはさまざまな目的を果たし、さまざまな抽象化レベルで存在します。解決しようとしている問題に適したものを使用する必要があります。

リフレクションは汎用のイントロスペクションメカニズムであり、クラスのメンバーの列挙(Class.getMethods())、アクセシビリティフラグなどのメンバーの特性の検査など、メソッドハンドルメカニズムにはない多くの機能が含まれています。メンバーの一般的な署名などを検査する。

さらに、アクセスチェックは呼び出しごとに行われるため、リフレクティブオブジェクトは、共有者へのアクセスを許可せずに自由に共有できます。メソッドハンドルは、共有者に呼び出す機能を付与します。したがって、セキュリティへの影響も異なります。

メソッドハンドルは、メソッドを検索、適合、および呼び出すための低レベルのメカニズムです。メソッドハンドルを介した呼び出しはリフレクションを介した呼び出しよりも高速ですが(これまでのところ、直接バイトコード呼び出しは一般にメソッドハンドル呼び出しよりも高速です)、メソッドハンドルは自動的に適応を実行しないため、使用が非常に困難ですJavaユーザーが期待する(String引数をObjectに変換するなど)ため、リンケージエラーが発生します。

リフレクションライブラリは主流のJavaユーザーを対象としています。メソッドハンドルレイヤーは、コンパイラと言語ランタイムの作成者を対象としています。ジョブ用に設計されたツールを選択してください。

28
Brian Goetz

tl; drいいえ。可能な場合は、Core ReflectionAPIよりもMethodHandlesを使用する(そして優先する)必要があります。

MethodHandles.Lookup access (部分的に)言う、

リフレクティブメソッドが呼び出されるたびにアクセスがチェックされるCoreReflection APIとは異なり、メソッドハンドルのアクセスチェックが実行されます メソッドハンドルの作成時

3
Elliott Frisch