クラスLambdaMetafactory
おそらく型適応と引数の部分評価の後に、指定されたMethodHandleへの委譲によって、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にするメソッド。 これらのメソッドは一般に、invokedynamicコール・サイトのブートストラップ・メソッドとして使用され、Javaプログラミング言語のラムダ式およびメソッド参照式機能をサポートします。
提供されたMethodHandleによって指定された動作への間接アクセスは、3つのフェーズで順番に進行します。
リンケージ。このクラスのメソッドが呼び出されたときに発生します。 引数として、実装するインタフェース(通常、「機能インタフェース」は単一の抽象メソッドを持ちます)、実装するインタフェースからのメソッドの名前およびシグネチャ、そのメソッドに必要な実装動作を記述する「ダイレクト・メソッド・ハンドル」、およびその他の追加メタデータ、および適切なファンクション・オブジェクトの作成にターゲットを使用できる
CallSiteを生成します。リンクには、ターゲット・インタフェースを実装する新しいクラスを動的にロードしたり、適切な既存クラスを再利用したりすることが必要な場合があります。
CallSiteは関数オブジェクトのファクトリと見なすことができるため、これらのリンケージ・メソッドはメタファクトリと呼ばれます。キャプチャ。
CallSiteのターゲットが呼び出されるときに発生し(一般的にinvokedynamicコール・サイトによって)、関数オブジェクトを生成します。 これは、単一ファクトリCallSiteに対して何度も発生する場合があります。動作
MethodHandleに、指定されたインタフェース・メソッドのパラメータ以外の追加パラメータがある場合、これらは「取得されたパラメータ」と呼ばれます。これは、CallSiteターゲットの引数として指定する必要があります。 取得されるパラメータの数およびタイプは、リンク時に決定されます。取得には、新しい関数オブジェクトの割当てが含まれることも、適切な既存の関数オブジェクトを返す場合もあります。 取得によって生成されたファンクション・オブジェクトのアイデンティティは予測不能であるため、アイデンティティに敏感な操作(参照等価、オブジェクト・ロック、
System.identityHashCode()など)では、異なる実装、または同じ実装での異なる呼出しでさえ異なる結果になる場合があります。呼出し。実装されたインタフェース・メソッドが関数オブジェクトで呼び出されたときに発生します。 これは、単一関数オブジェクトに対して何度も発生する場合があります。 実装
MethodHandleによって参照されるメソッドが呼び出され、取得された引数および呼出し引数に渡されます。 メソッドの結果が返されます。
呼出しで許可される入力または結果のセットを制限することが便利な場合があります。 たとえば、ジェネリック・インタフェースPredicate<T>がPredicate<String>としてパラメータ化されるときは、入力はStringである必要があります(実装するメソッドが任意のObjectを許可していても)。 リンク時に、追加のMethodTypeパラメータは"動的"メソッド・タイプを記述します。起動時には、引数および最終結果がこのMethodTypeに対してチェックされます。
このクラスは2つの形式のリンケージ・メソッドを提供します。最適化されたプロトコルを使用する標準版(metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType))と、代替版(altMetafactory(MethodHandles.Lookup, String, MethodType, Object...))です。 代替版は標準版の一般化したもので、フラグおよび追加引数を介して生成された関数オブジェクトの動作に対する追加制御を提供します。 代替版では、関数オブジェクトの次の属性を管理する機能が追加されます。
- 複数のメソッド。 引数または戻り型の適応を含む、メソッド・シグネチャの複数のバリエーションを実装するのに役立つ場合があります。 これは、メソッドの複数の異なるVMシグネチャが、言語によって論理的に同じメソッドであると見なされるときに発生します。 フラグ
FLAG_BRIDGESは、追加のMethodTypeのリストが提供されることを示します(それぞれが結果の関数オブジェクトによって実装される)。 これらのメソッドは同じ名前およびインスタンス化された型を共有します。 - 複数のインタフェース。 必要に応じて、関数オブジェクトは複数のインタフェースを実装できます。 (これらの追加インタフェースは一般的に、メソッドなしのマーカー・インタフェースです。) フラグ
FLAG_MARKERSは、追加インタフェースのリストが提供されることを示します(それぞれが結果の関数オブジェクトによって実装される)。 - 直列化可能性。 生成された関数オブジェクトは一般的に直列化をサポートしません。 必要に応じて、関数オブジェクトが直列化可能であるべきことを示すために
FLAG_SERIALIZABLEを使用できます。 直列化可能関数オブジェクトは、キャプチャ・クラス(MethodHandles.Lookupのパラメータcallerによって記述されるクラス)からの追加支援を必要とする、SerializedLambdaクラスのインスタンスを、直列化形式として使用します。詳細は、SerializedLambdaを参照してください。
リンケージ引数は次のことを前提とします。
factoryType(CallSiteシグネチャの説明)には、タイプ(D1..Dk)および戻り型RdのKパラメータがありますinterfaceMethodType(実装されたメソッド・タイプの説明)には、タイプ(U1..Un)および戻り型RuのNパラメータがありますimplementation(実装を提供するMethodHandle)には、タイプ(A1..Am)および戻り型Ra (メソッドがインスタンス・メソッドを記述する場合、このメソッド・ハンドルのメソッド・タイプには、受信側に対応する追加の第1引数がすでに含まれています)のMパラメータがありますdynamicMethodType(起動時の制限の許可)には、タイプ(T1..Tn)および戻り型RTのNパラメータがあります。
さらに、次のリンケージ不変条件を保持する必要があります。
interfaceMethodTypeとdynamicMethodTypeは同じアリティNを持ち、i=1..Nの場合、TiとUiは同じタイプであるか、TiとUiの両方が参照タイプであり、TiはUiのサブタイプです- RtおよびRuが同じ型、または両方が参照型かつRtがRuのサブタイプ
- K + N = M
- i=1..Kの場合、Di = Ai
- i=1..Nの場合、TiはAjに適応可能、j=i+k
- 戻り型Rtがvoid、または戻り型RaがvoidでなくRtに適応可能
また、取得時にimplementationがインスタンス・メソッドに対応し、取得引数(K > 0)がある場合、最初の取得引数(レシーバに対応)はNULL以外である必要があります。
次のように型QはSに適応可能と見なされます。
| Q | S | リンク時チェック | 呼出し時チェック |
|---|---|---|---|
| プリミティブ | プリミティブ | Qはプリミティブ・ワイドニング変換でSに変換可能 | なし |
| プリミティブ | リファレンス | SはWrapper(Q)のスーパータイプ | Wrapper(Q)からSにキャスト |
| リファレンス | プリミティブ | パラメータ型の場合: Qはプリミティブ・ラッパー、Primitive(Q)はSにワイドニング可能 戻り型の場合: Qがプリミティブ・ラッパーの場合はPrimitive(Q)がSにワイドニング可能かをチェック |
Qがプリミティブ・ラッパーでない場合、Qを基底Wrapper(S)にキャスト。たとえば、数値型の場合はNumber |
| リファレンス | リファレンス | for parameter types: S is a supertype of Q for return types:なし |
QからSにキャスト |
- APIのノート:
- これらのリンケージ・メソッドはJava言語のラムダ式およびメソッド参照の評価をサポートするように設計されています。 ソース・コード内のすべてのラムダ式またはメソッド参照に、関数型インタフェースであるターゲット型が存在します。 ラムダ式を評価することで、そのターゲット型のオブジェクトが生成されます。 ラムダ式の評価で推奨されるメカニズムは、メソッドのラムダ本文を脱糖し、invokedynamicコール・サイト(静的引数リストが関数型インタフェースの唯一のメソッドおよび脱糖された実装メソッドを記述し、ターゲット型を実装するオブジェクト(ラムダ・オブジェクト)を返す)を呼び出すことです。 (メソッド参照の場合、実装メソッドは単に参照されるメソッドです、脱糖は必要ありません。)
実装メソッドの引数リストとインタフェース・メソッドの引数リストはいくつかの点で異なる場合があります。 実装メソッドは、ラムダ式によってキャプチャされる引数に対応するために追加引数を持つ場合があります。引数に許可された適応(キャスト、ボクシング、アンボクシング、プリミティブ・ワイドニングなど)による違いがある場合もあります。 (可変引数適応はメタファクトリによって扱われません。これらは呼出し元によって扱われることが期待されます。)
invokedynamicコール・サイトには2つの引数リスト、静的引数リストと動的引数リストがあります。 静的引数リストは定数プールに格納されますが、動的引数はキャプチャ時にオペランド・スタックにプッシュされます。 ブートストラップ・メソッドは、静的引数リスト全体(この場合、実装メソッド、ターゲット・インタフェースおよびターゲット・インタフェース・メソッドを記述する情報を含む)、動的引数の数と静的な型(ただし値ではない)およびinvokedynamicサイトの静的な戻り型を記述するメソッド・シグネチャにアクセスできます。
実装メソッドは、メソッドまたはコンストラクタを参照する直接メソッド・ハンドルを使用して記述します。 理論的には、メソッド・ハンドルを使用できますが、これは実装手法と互換性がなく、作業実装が複雑になる場合があります。
ラムダ式の評価に加えて、メソッド参照も意図されていません。 これらのリンケージ・メソッドは、サポートするように設計されたJava言語機能に適合するように、未指定の動作をいつでも変更でき、そのような変更は意図しない使用に影響を与える可能性があります。 これらのリンケージ・メソッドの意図しない使用は、リソース・リーク、またはその他の不特定の悪影響を引き起こす可能性があります。
- 実装上のノート:
- リファレンス実装では、作成された関数オブジェクトを実装するクラスは、Javaソース・コード内のクラスやインタフェースなど、コール元の定義クラス・ローダーから強くアクセスできます。 この方法により、ヒープ・メモリーの使用量が削減されますが、その結果、実装クラスをアンロードできるのは、コール元クラスをアンロードできる場合のみです。 特に、コール元が「弱い隠されたクラス」の場合、実装クラス(強力な非表示クラス)は、コール元がアンロードされていてもアンロードされないことがあります。
- 導入されたバージョン:
- 1.8
-
フィールドのサマリー
フィールド修飾子と型フィールド説明static final intラムダ・オブジェクトを示す代替メタ・ファクタのフラグには、implementationを起動する追加メソッドが必要ですstatic final intラムダ・オブジェクトがSerializable以外のインタフェースを実装することを示すaltMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...)のフラグstatic final intラムダ・オブジェクトが直列化可能である必要があることを示すaltMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...)のフラグ -
メソッドのサマリー
修飾子と型メソッド説明static CallSitealtMetafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, Object... args) 適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。static CallSitemetafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, MethodType interfaceMethodType, MethodHandle implementation, MethodType dynamicMethodType) 適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。
-
フィールド詳細
-
FLAG_SERIALIZABLE
public static final int FLAG_SERIALIZABLEラムダ・オブジェクトが直列化可能である必要があることを示すaltMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...)のフラグ- 関連項目:
-
FLAG_MARKERS
public static final int FLAG_MARKERSラムダ・オブジェクトがSerializable以外のインタフェースを実装することを示すaltMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...)のフラグ- 関連項目:
-
FLAG_BRIDGES
public static final int FLAG_BRIDGESラムダ・オブジェクトを示す代替メタ・ファクタのフラグには、implementationを起動する追加メソッドが必要です- 関連項目:
-
-
メソッドの詳細
-
metafactory
public static CallSite metafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, MethodType interfaceMethodType, MethodHandle implementation, MethodType dynamicMethodType) throws LambdaConversionException 適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。 一般的にinvokedynamicコール・サイトのブートストラップ・メソッドとして、Javaプログラミング言語のラムダ式およびメソッド参照式機能をサポートするために使用されます。これは標準の、合理化されたメタファクトリです。
altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)によってより高い柔軟性が提供されます。 このメソッドの動作の概要はすでに説明済です。このメソッドから返された
CallSiteのターゲットが呼び出されると、結果として得られる関数オブジェクトは、戻り値のfactoryTypeという名前のインタフェースを実装するクラスのインスタンスであり、interfaceMethodNameおよびinterfaceMethodTypeによって指定される名前のメソッドが宣言されます。Objectからの追加メソッドをオーバーライドすることもできます。- パラメータ:
caller- 呼出し元のアクセス可能性権限を持つルックアップ・コンテキストを表します。 特に、参照コンテキストには「完全な権限アクセス」が必要です。invokedynamicで使用されるときは、これはVMによって自動的にスタックされます。interfaceMethodName- 実装メソッドの名前。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。factoryType-CallSiteの予想されるシグネチャ。 パラメータ型はキャプチャ変数の型を表し、戻り型は実装するインタフェースです。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。interfaceMethodType- 関数オブジェクトによって実装されるメソッドのシグネチャおよび戻り型。implementation- 起動時に(引数の型と戻り型への適切な適応と、起動引数の前に取得された引数を使用)と呼ばれる実装メソッドを記述する直接メソッド・ハンドル。dynamicMethodType- 起動時に動的に適用するシグネチャと戻り型。 単純なユースケースでは、これはinterfaceMethodTypeと同じです。- 戻り値:
- ターゲットを使用して取得を実行し、
factoryTypeという名前のインタフェースのインスタンスを生成できるCallSite - スロー:
LambdaConversionException-callerに完全な権限アクセス権がない場合、またはinterfaceMethodNameが有効なJVMメソッド名でない場合、またはfactoryTypeの戻りタイプがインタフェースでない場合、またはimplementationがメソッドまたはコンストラクタを参照する直接メソッド・ハンドルでない場合、または定義済のaboveのようにリンク不変者に違反している場合。NullPointerException- 引数がnullの場合。
-
altMetafactory
public static CallSite altMetafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, Object... args) throws LambdaConversionException 適切な型適応および引数の部分評価の後、指定されたMethodHandleへの委譲により、1つ以上のインタフェースを実装する単純な関数オブジェクトの作成を容易にします。 一般的にinvokedynamicコール・サイトのブートストラップ・メソッドとして、Javaプログラミング言語のラムダ式およびメソッド参照式機能をサポートするために使用されます。これは一般的で、柔軟性の高いメタファクトリです。合理化されたバージョンが
metafactory(java.lang.invoke.MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)によって提供されます。 このメソッドの動作の概要はすでに説明済です。このメソッドの引数リストには3つの固定パラメータが含まれ、
invokedynamic呼出しでブートストラップ・メソッドのためにVMによって自動的にスタックされるパラメータと、追加パラメータを含むObject[]パラメータに対応しています。 このメソッドに宣言される引数リストは次のとおりです。CallSite altMetafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, Object... args)しかし、引数リストが以下であるかのように動作します。
CallSite altMetafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, MethodType interfaceMethodType, MethodHandle implementation, MethodType dynamicMethodType, int flags, int altInterfaceCount, // IF flags has MARKERS set Class... altInterfaces, // IF flags has MARKERS set int altMethodCount, // IF flags has BRIDGES set MethodType... altMethods // IF flags has BRIDGES set )metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)の引数リスト内の引数は、そのメソッド内と同じ仕様を持ちます。 追加引数は次のように解釈されます。flagsは追加オプションを示します。これは、必要なフラグのビット単位ORです。 定義済フラグはFLAG_BRIDGES、FLAG_MARKERSおよびFLAG_SERIALIZABLEです。altInterfaceCountは、ファンクション・オブジェクトが実装する必要のある追加インタフェースの数で、FLAG_MARKERSフラグが設定されている場合にのみ存在します。altInterfacesは、実装する追加インタフェースの可変長リストで、長さはaltInterfaceCountで、FLAG_MARKERSフラグが設定されている場合にのみ存在します。altMethodCountは、ファンクション・オブジェクトが実装する必要がある追加のメソッド・シグネチャの数で、FLAG_BRIDGESフラグが設定されている場合にのみ存在します。altMethodsは、実装する追加メソッド・シグネチャの可変長リストで、長さはaltMethodCountであり、FLAG_BRIDGESフラグが設定されている場合にのみ存在します。
altInterfacesで指定された各クラスは、aboveで説明されているように、Rd(factoryTypeの戻り型)と同じ制限に従います。altMethodsで指定された各MethodTypeは、aboveで説明されているように、interfaceMethodTypeと同じ制限に従います。flagsにFLAG_SERIALIZABLEが設定されているとき、関数オブジェクトはSerializableを実装し、適切なSerializedLambdaを返すwriteReplaceメソッドを持ちます。callerクラスは、SerializedLambdaで説明したとおり適切な$deserializeLambda$メソッドを持つ必要があります。このメソッドから返される
CallSiteのターゲットが呼び出されるとき、結果の関数オブジェクトは次のプロパティを持つクラスのインスタンスです。- クラスは、
factoryTypeの戻り型およびaltInterfacesによって命名されたインタフェースを実装 - クラスは、
interfaceMethodNameで指定された名前と、interfaceMethodTypeによって与えられたシグネチャ、およびaltMethodsによって指定される追加のシグネチャを含むメソッドを宣言 - このクラスは
Objectからのメソッドをオーバーライドでき、直列化に関連するメソッドを実装できます。
- パラメータ:
caller- 呼出し元のアクセス可能性権限を持つルックアップ・コンテキストを表します。 特に、参照コンテキストには「完全な権限アクセス」が必要です。invokedynamicで使用されるときは、これはVMによって自動的にスタックされます。interfaceMethodName- 実装メソッドの名前。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。factoryType-CallSiteの予想されるシグネチャ。 パラメータ型はキャプチャ変数の型を表し、戻り型は実装するインタフェースです。invokedynamicで使用されるときは、これはInvokeDynamic構造のNameAndTypeによって提供され、VMによって自動的にスタックされます。args- 前述のとおり、必要な引数interfaceMethodType,implementation,dynamicMethodType,flagsおよび任意のオプションの引数を含むObjectの配列- 戻り値:
- ターゲットを使用して取得を実行し、
factoryTypeという名前のインタフェースのインスタンスを生成できるCallSite - スロー:
LambdaConversionException-callerに完全な権限アクセス権がない場合、またはinterfaceMethodNameが有効なJVMメソッド名でない場合、またはfactoryTypeの戻りタイプがインタフェースでない場合、またはaltInterfacesのいずれかがインタフェースでない場合、またはimplementationがメソッドまたはコンストラクタを参照する直接メソッド・ハンドルでない場合、またはaboveの定義に従ってリンク不変者に違反している場合。NullPointerException- いずれかの引数またはargsのコンポーネントがnullの場合。IllegalArgumentException-argsのコンポーネントの数またはタイプが前述のルールに従っていない場合、またはaltInterfaceCountまたはaltMethodCountが負の整数である場合。
-