java.lang.invoke
パッケージには、Javaコア・クラス・ライブラリおよび仮想マシンによって直接提供される動的言語サポートが含まれています。参照: 説明
インタフェース | 説明 |
---|---|
MethodHandleInfo |
直接メソッド・ハンドルをその構成要素シンボリック部分に解決することによって取得されるシンボリック参照。
|
クラス | 説明 |
---|---|
CallSite | |
ConstantCallSite |
ConstantCallSite は、永続的で決して変更できないターゲットを持つCallSite です。 |
LambdaMetafactory |
おそらく型適応と引数の部分評価の後に、指定された
MethodHandle への委譲によって、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にするメソッド。 |
MethodHandle |
メソッド・ハンドルとは、ベースとなるメソッド、コンストラクタ、フィールド、または類似の低レベル操作に対する、直接実行可能な型付きの参照のことであり、オプションで引数や戻り値の変換も行います。
|
MethodHandleProxies |
このクラスはstaticメソッドのみで構成され、メソッド・ハンドルをインタフェースなどのその他のJVM型に適応させるときに役立ちます。
|
MethodHandles |
このクラスは、メソッド・ハンドルに対する処理を行うかメソッド・ハンドルを返すstaticメソッドだけで構成されます。
|
MethodHandles.Lookup |
ルックアップ・オブジェクトは、メソッド・ハンドルの作成にアクセス・チェックが必要な場合のメソッド・ハンドル作成用ファクトリです。
|
MethodType |
メソッド型は、メソッド・ハンドルが受け取ったり返したりする引数や戻り値の型、あるいはメソッド・ハンドルの呼出し元が渡したり期待したりする引数や戻り値の型を表します。
|
MutableCallSite |
MutableCallSite は、ターゲット変数の動作が通常のフィールドと同じであるようなCallSite です。 |
SerializedLambda |
ラムダ式の直列化された形式。
|
SwitchPoint |
SwitchPoint は、状態遷移をほかのスレッドに発行できるオブジェクトです。 |
VolatileCallSite |
VolatileCallSite は、ターゲットの動作がvolatile変数と同じであるようなCallSite です。 |
例外 | 説明 |
---|---|
LambdaConversionException |
LambdaConversionException
|
WrongMethodTypeException |
コード内でメソッド・ハンドルを不正なメソッド型経由で呼び出そうとしたことを示すためにスローされます。
|
java.lang.invoke
パッケージには、Javaコア・クラス・ライブラリおよび仮想マシンによって直接提供される動的言語サポートが含まれています。
Java仮想マシン仕様で説明されているように、このパッケージ内の特定の型と、仮想マシンの動的言語サポートには、特別な関係があります。
MethodHandle
には、型記述子に関係なくリンク可能なシグネチャ・ポリモーフィズム・メソッドが含まれています。通常、メソッドのリンク時には型記述子が厳密に一致する必要があります。
MethodHandle
とMethodType
の即値定数がサポートされます。
invokedynamic
命令の個々の出現は動的コール・サイトと呼ばれます。
invokedynamic
命令
JVMが動的コール・サイト(invokedynamic
命令)を実行するには、そのコール・サイトをまずリンクする必要があります。リンクはブートストラップ・メソッドを呼び出すことで実現されますが、このメソッドは、与えられたコール・サイトの静的な情報コンテンツに基づいて、コール・サイトの動作を与えるメソッド・ハンドル
を生成する必要があります。
各invokedynamic
命令は、自身のブートストラップ・メソッドを定数プール参照として静的に指定します。invokevirtual
やその他の呼出し命令の場合とまったく同じく、この定数プール参照はコール・サイトの名前と型記述子も指定します。
リンク処理ではまず、ブートストラップ・メソッドの定数プール・エントリの解決と、動的コール・サイトの型記述子のMethodType
オブジェクトの解決が行われます。この解決プロセスでクラスのロード処理がトリガーされる可能性があります。したがって、クラスのロードに失敗した場合に、エラーがスローされる可能性があります。このエラーは、動的コール・サイト実行の異常終了になります。リンクではクラスの初期化はトリガーされません。
ブートストラップ・メソッドの呼出し時には少なくとも3つの値が渡されます。
MethodHandles.Lookup
(動的コール・サイトの発生元である呼出し元クラス上のルックアップ・オブジェクト) String
(コール・サイト内で言及されたメソッド名) MethodType
(呼出しの解決済みの型記述子) MethodHandle.invoke
を使用したかのように行われます。返される結果は、CallSite
(またはサブクラス)でなければいけません。このコール・サイトのターゲットの型は、動的コール・サイトの型記述子から派生されてブートストラップ・メソッドに渡された型と、厳密に等しくなければいけません。このコール・サイトはその後、その動的コール・サイトに永続的にリンクされた状態になります。
JVM仕様にドキュメント化されているように、動的コール・サイトのリンクに起因する失敗はすべてBootstrapMethodError
として報告されますが、これは、動的コール・サイト実行の異常終了としてスローされます。これが発生した場合、動的コール・サイトを実行する後続のすべての試みで、同じエラーがスローされます。
そのようなスレッドがいくつか存在する場合、ブートストラップ・メソッドがいくつかのスレッド内で並行して呼び出される可能性があります。したがって、グローバル・アプリケーション・データにアクセスするブートストラップ・メソッドでは、競合状態に対する通常の予防策を講じる必要があります。いずれにせよ、すべてのinvokedynamic
命令は、リンクされていない状態、一意のCallSite
オブジェクトにリンクされた状態、のいずれかになります。
個別に変更可能な動作を備えた動的コール・サイトが必要なアプリケーションでは、ブートストラップ・メソッドはそれぞれ異なるCallSite
オブジェクトを生成すべきです(リンク要求ごとに1つずつ)。また、アプリケーションでは単一のCallSite
オブジェクトをいくつかのinvokedynamic
命令にリンクすることもできますが、その場合、ターゲット・メソッドへの変更がすべての命令で可視になります。
単一の動的コール・サイトのブートストラップ・メソッドがいくつかのスレッド内で同時に実行された場合、JVMは1つのCallSite
オブジェクトを選択し、それをすべてのスレッドにインストールして可視状態にする必要があります。ほかのすべてのブートストラップ・メソッド呼出しは完了まで実行を許可されますが、それらの結果は無視され、それらの動的コール・サイト呼出しは、最初に選択されたターゲット・オブジェクトを使って処理されます。
解説: これらのルールにより、JVMが動的コール・サイトの複製や「偶発的な」ブートストラップ・メソッド呼出しの発行を行えるようになるわけではありません。どの動的コール・サイトでも、未リンクからリンク済みへの遷移は、最初の呼出しの直前に最大1回しか行われません。完了したブートストラップ・メソッド呼出しの効果を取り消す方法はありません。
MethodHandle.invoke
で正しく呼び出せるかぎり、その詳細な型は任意となります。たとえば、最初の引数をMethodHandles.Lookup
ではなくObject
にしてもかまいませんし、戻り値の型もCallSite
ではなくObject
にすることができます。(スタック内の引数の型と数により、適合するブートストラップ・メソッドの種類が、CallSite
サブクラスの適切に型付けされたstaticメソッドおよびコンストラクタに制限されます。)
特定のinvokedynamic
命令に静的な引数が1つも指定されていない場合、その命令のブートストラップ・メソッドが3つの引数(命令の呼出し元クラス、名前、およびメソッド型)で呼び出されます。invokedynamic
命令に1つ以上の静的引数が指定されている場合、それらの値は追加の引数としてメソッド・ハンドルに渡されます。(すべてのメソッドの引数には255個という上限が存在するので、最大251個の追加引数を指定できます。これは、ブートストラップ・メソッド・ハンドル自体とその最初の3つの引数も、スタックに格納しなければいけないからです。)ブートストラップ・メソッドの呼出しは、MethodHandle.invoke
またはinvokeWithArguments
のいずれかを使用したかのように行われます。(その違いを区別する方法はありません。)
MethodHandle.invoke
の通常の引数変換ルールが、スタック内のすべての引数に適用されます。たとえば、プッシュされる値がプリミティブ型であった場合、それはボクシング変換によって参照に変換される可能性があります。ブートストラップ・メソッドが可変引数メソッドである(修飾子ビット0x0080
が設定されている)場合、ここに指定された引数の一部または全部が末尾の配列パラメータ内に集められる可能性があります。(これは特殊なルールでなく、CONSTANT_MethodHandle
定数、可変引数メソッド用の修飾子ビット、およびasVarargsCollector
変換の間の相互作用の有用な結果です。)
以上のルールに基づき、追加引数のさまざまな個数N
ごとに、正しいブートストラップ・メソッド宣言の例を次に示します。最初の数行(*
の付いたもの)は、任意の数の追加引数で動作します。
N | サンプルのブートストラップ・メソッド |
---|---|
* | CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args) |
* | CallSite bootstrap(Object... args) |
* | CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs) |
0 | CallSite bootstrap(Lookup caller, String name, MethodType type) |
0 | CallSite bootstrap(Lookup caller, Object... nameAndType) |
1 | CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg) |
2 | CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args) |
2 | CallSite bootstrap(Lookup caller, String name, MethodType type, String... args) |
2 | CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y) |
CONSTANT_String
とCONSTANT_Integer
であると仮定しています。最後から2番目の例では、すべての追加引数の型がCONSTANT_String
であると仮定しています。その他の例は、あらゆる型の追加引数で動作します。
前述したように、ブートストラップ・メソッドの実際のメソッド型は変更可能です。たとえば、4番目の引数はMethodHandle
でもかまいません(それがCONSTANT_InvokeDynamic
エントリ内の対応する定数の型である場合)。その場合、MethodHandle.invoke
の呼出しでは追加メソッド・ハンドル定数がObject
として渡されますが、MethodHandle.invoke
の型一致機構によってその参照が元のMethodHandle
にキャストされたあと、ブートストラップ・メソッドが呼び出されます。(不適切に生成されたコードによって文字列定数が代わりに渡された場合、そのキャストは失敗し、BootstrapMethodError
が発行されます。)
上記のルールの結果として、ブートストラップ・メソッドを定数プール・エントリで表現できる場合は、それがプリミティブ引数を受け入れる可能性があることに注意してください。ただし、型がboolean
、byte
、short
、またはchar
の引数をブートストラップ・メソッド用に作成することはできず(そのような定数を定数プールで直接表現することができないため)、ブートストラップ・メソッドを呼び出しても必要なナロー・プリミティブ変換は行われません。
ブートストラップ・メソッドの追加引数の目的は、言語実装者がメタデータのエンコードを安全かつコンパクトに行えるようにすることです。原則として名前引数や追加引数は冗長になりますが、それは、各コール・サイトにそれぞれ一意のブートストラップ・メソッドが指定される可能性があるからです。そのような運用ではおそらく、大きなクラス・ファイルや定数プールが生成されます。
バグまたは機能を送信
詳細なAPIリファレンスおよび開発者ドキュメントについては、Java SEのドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright© 1993, 2014, Oracle and/or its affiliates. All rights reserved.