問題タブ [methodhandle]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - MethodType は問題ないのに、ここで .invokeExact() を実行できないのはなぜですか?
私のプロジェクトの 1 つで、コンストラクターを動的に呼び出す必要があります。しかし、これは Java 7 であるため、「従来の」リフレクション API ではなく、java.lang.invoke を使用します。
コード:
わかりました、これはうまくいきます。
私が抱えている問題は、次の行にあります。
に置き換えるinvoke
とinvokeExact
、次のスタック トレースが得られます。
よくわかりません。と の両方が引数としてa を持つ単一のコンストラクターを使用するGlobPathMatcher
ため、 for both は で定義されているものです。そうでなければ、とにかく sを「つかむ」ことはできませんでした。RegexPathMatcher
String
MethodType
CONSTRUCTOR_TYPE
MethodHandle
それでも私はWrongMethodTypeException
. なんで?
編集:答えを読んだ後のコードは次のとおりです。今は中間マップは必要ありません: aString
を aにマッピングする 1 つのマップが必要ですMethodHandle
:
java - MethodHandle::invokeExact をメソッド参照として使用したために発生した LambdaConversionException によって発生した BootstrapMethodError
MethodHandle::invoke または MethodHandle::invokeExact を、MethodHandle を受け入れて生成された出力を返す関数インターフェイスのメソッド参照として使用できるかどうかを確認しようとしていました。
(invoke と invokeExact はシグネチャ ポリモーフィックであるため、InvokeExact でのメタファクトリ呼び出しであることはわかっています。ただし、invoke/invokeExact の適切なバージョンを派生させるために必要だった作業をコンパイラが省略できるかどうかを知りたかったのです。)
呼び出す.InvokeExact0
結果
良いニュースは、メタファクトリ アプローチが機能する機能インターフェイス インスタンスを合成できたことです (印刷されているように: invoke.InvokeExact0$$Lambda$1/1878246837@1be6f5c3 )。悪いニュースは、メソッド参照アプローチが LambdaConversionException を引き起こし、それがさらに BootstrapMethodError を引き起こしたことです。
とにかくメタファクトリの回避策が存在するため、LambdaConversionException のエラーの詳細をどのように解釈することになっているのかを尋ねたいと思います。
java - Lambda メソッド参照のためのわかりやすい toString
toString
メソッドハンドルで生成されたラムダを理解できるようにする方法はありますか? Java 8 より前のFunction
バージョンでは、Guava のインターフェースを使用しており、多くのデータ クラスの関数を生成するスクリプトを作成しました。また、クラスとメソッドを明確に識別できるも含めましたtoString
。たとえば、「MyItem::getPrice」です。
しかし、Java 8 では、関数の宣言ははるかに簡単になりましたが、関数が何であるかを特定する方法がなくなりました。nice の最も重要な理由はtoString
デバッグ目的ですが、他にもあると確信しています。この情報がリフレクションで利用できればいいのですが、明らかにそうではありません。
このコード スニペット
生産する
ご覧のとおり、操作するラムダ スーパークラスさえありません。
明確化
独自の を定義する方法を尋ねているのではなくtoString
、このラムダが呼び出しているクラス/メソッドを特定する方法を尋ねています。自分で定義すると、 toString
Java 8 ラムダを使用する目的全体が無効になります。適切なtoString
. ラムダなしで自動化されたスクリプトを使用することもできます。
java - MethodHandle InvokeExact パラメータ
メソッド ハンドルのメソッド パラメータがわかりません。まず、以下に示すように、test メソッド ハンドルを使用してガードを作成します。
私にとっての問題は、パラメーターが 3 つのメソッド ハンドル (test、trueTarget、および faliover) にどのように渡されるかということです。1、invokeExact の最初のパラメーター「result」がレシーバーとしてテスト ガードに渡され、2 番目のパラメーター「data」が startWith に渡されます。
But the these three parameters are passed to the falseTarget as:
So, what's the rule for parameters passing and how do they match to the methods referenced by a method handle?
java - タイプがクラスローダーによって動的にロードされるオブジェクトの InvokeExact
私はこの問題に一日を費やしました。私の問題は、クラス型がプログラムの実行時に動的にロードされるインスタンスで MethodHandle.invokeExact 呼び出しを行う方法です。問題をより明確にするために、サンプルコードを以下に示します。
このサンプルでは、expClass が動的にロードされ、そのクラス タイプはAddSample
です。次の行の obj インスタンスは BaseTemplate であると宣言されており、その実際の型はAddSample
. クラス AddSample は BaseTemplate のサブクラスです。次に、メソッドハンドル myMh を add 関数に作成しAddSample
ますが、receiverType が一致しないため、myMH の呼び出しは失敗します。
はmyMH.invokeExact
実行時エラーを発生させます
this のレシーバーはmyMH
expClass (AddSample) にあると宣言されてobj
いますが、obj のクラスは AddSample ですが、現在提供されているレシーバーは BaseTemaplte と宣言されているためです。InvokeExact では、パラメーターが正確に一致する必要があります。
私の問題は次のように単純化される可能性があります:インスタンスをその基本型から動的にロードされる子型にキャストする方法は?
obj の宣言された型を、動的にロードされる AddSample に変更します..?
UPDATE:
キャストを使用しても、以前の結果と同じ問題を解決するのには役立ちません。その理由は、指定されたパラメーターが myMH 宣言と完全に一致していないためです。生成されたバイトコードを確認すると、より明確になります。
myMH は を指して
(AddSample,String,int,float)int
いますが、パラメーター:
(Object, String, int, float)
を指定すると、前に示した実行時エラーが発生します。
ありがとう
java - 戻り値の型 (強制キャスト) が MethodHandler のパフォーマンスにおいて重要なルールを果たしているのはなぜですか?
私は単純なプロジェクトに取り組んでおり、Bean プロパティを取得する必要があります。まず、リフレクションを使用します。次に、パフォーマンスを向上させるために、invokedynamic とメソッド ハンドラーについて調査を行いました。
インボークinvokeExact
はリフレクションよりもはるかに高速ですが、リフレクションよりもはるかに低速です。
テスト環境:
- Win7 32ビット
- ジャワ 7 U 80
- コアによるCPU 3.06GHZ
私が得たtp / msはこれについてです:
パフォーマンス テストの出力は次のとおりです (2 回実行しました)。
ここに私のテストコードがあります:
invokeExact
コンパイル時に正確な戻り値の型がわからないため、ユース ケースを満たすことができません。リターンの型(強制キャスト)がMethodHandle
の性能を左右する重要な鍵のようです。
MethodType
の戻り値の型が正確であるため、これは予期された結果ではないようです。パフォーマンスを向上させるためにフォースキャストを行うことが依然として重要なのはなぜですか?
これに関する詳細を説明するドキュメントはありますか? また、リフレクションとメソッド ハンドラの使用の impl の詳細を比較するドキュメントはありますか?
java - MethodHandle の方が速いのに、なぜリフレクションを使用してクラス メンバーにアクセスするのですか?
Java 7 のリリースに伴い、MethodHandle
ユーザーはメソッドを基になるバイトコードを使用しているかのように呼び出すことができます。特に、このMethodHandles.Lookup
クラスは、クラス メンバーにアクセスするためのメソッド ハンドルを作成するファクトリ メソッドを提供します。
Lookup オブジェクトのファクトリ メソッドは、メソッド、コンストラクタ、およびフィールドのすべての主要なユース ケースに対応しています。ファクトリ メソッドによって作成された各メソッド ハンドルは、特定のバイトコード動作と機能的に同等です。
機能的には、これはリフレクションを使用してこれらの同じクラス メンバーにアクセスするのとほぼ同等ですが、メソッド ハンドルはリフレクションよりも高速です。
それで、まだリフレクション機能を使用する理由はありますかField#get(..)
/Method.invoke(..)
またはこれらのメソッドは、より高速なメソッドハンドルの導入により事実上廃止されていますか?
メソッドハンドルは Java 7 で導入されましたが、私の質問は主に Java 8 に関するものであることに注意してください。Java 8 では、直接フィールド/メソッド呼び出しとほぼ同等のパフォーマンスに達するように最適化されており、リフレクションの能力を上回っています。