モジュール java.base
パッケージ java.lang.invoke

クラスMethodHandles.Lookup

java.lang.Object
java.lang.invoke.MethodHandles.Lookup
含まれているクラス:
MethodHandles

public static final class MethodHandles.Lookup
extends Object
ルックアップ・オブジェクトは、メソッド・ハンドルの作成にアクセス・チェックが必要な場合のメソッド・ハンドル作成用ファクトリです。 メソッド・ハンドルでアクセス・チェックが実行されるのは、その呼出し時ではなく作成時です。 したがって、メソッド・ハンドルのアクセス制限は、メソッド・ハンドルの作成時に適用する必要があります。 それらの制限の適用先となる呼出し元クラスは、ルックアップ・クラスと呼ばれます。

メソッド・ハンドルを作成する必要のあるルックアップ・クラスは、MethodHandles.lookupを呼び出して自分用のファクトリを作成します。 Lookupファクトリ・オブジェクトの作成時には、ルックアップ・クラスのアイデンティティが決定され、その情報がLookupオブジェクト内にセキュアに格納されます。 その後、ルックアップ・クラス(またはその委譲先)は、Lookupオブジェクトのファクトリ・メソッドを使ってアクセス・チェックされたメンバーのメソッド・ハンドルを作成できます。 これには、ルックアップ・クラスに許可されるメソッド、コンストラクタ、およびフィールドがすべて含まれます(privateのものも含む)。

Lookupファクトリ・メソッド

Lookupオブジェクトのファクトリ・メソッドは、メソッド、コンストラクタ、およびフィールドのすべてのメジャーなユース・ケースに対応しています。 ファクトリ・メソッドによって作成される各メソッド・ハンドルは、特定のバイトコード動作と機能的に同等です。 (バイトコード動作は『Java Virtual Machine Specification』のセクション5.4.3.5に記述されています。) これらのファクトリ・メソッドと、結果として得られるメソッド・ハンドルの動作との対応のサマリーを以下に示します:
ルックアップ・メソッドの動作
ルックアップ式 メンバー バイトコード動作
lookup.findGetter(C.class,"f",FT.class) FT f;(T) this.f;
lookup.findStaticGetter(C.class,"f",FT.class) static
FT f;
(FT) C.f;
lookup.findSetter(C.class,"f",FT.class) FT f;this.f = x;
lookup.findStaticSetter(C.class,"f",FT.class) static
FT f;
C.f = arg;
lookup.findVirtual(C.class,"m",MT) T m(A*);(T) this.m(arg*);
lookup.findStatic(C.class,"m",MT) static
T m(A*);
(T) C.m(arg*);
lookup.findSpecial(C.class,"m",MT,this.class) T m(A*);(T) super.m(arg*);
lookup.findConstructor(C.class,MT) C(A*);new C(arg*);
lookup.unreflectGetter(aField) (static)?
FT f;
(FT) aField.get(thisOrNull);
lookup.unreflectSetter(aField) (static)?
FT f;
aField.set(thisOrNull, arg);
lookup.unreflect(aMethod) (static)?
T m(A*);
(T) aMethod.invoke(thisOrNull, arg*);
lookup.unreflectConstructor(aConstructor) C(A*);(C) aConstructor.newInstance(arg*);
lookup.unreflectSpecial(aMethod,this.class) T m(A*);(T) super.m(arg*);
lookup.findClass("C") class C { ... }C.class;
ここで、型Cはメンバーが検索されるクラスまたはインタフェースで、ルックアップ・メソッド内でrefcという名前のパラメータとして記述されています。 メソッド型MTは、戻り型Tと引数型シーケンスA*から構成されます。 コンストラクタも引数型シーケンスA*を持ち、型Cの新しく作成されたオブジェクトを返すと見なされます。 MTとフィールドの型FTはどちらも、typeという名前のパラメータとしてドキュメント化されています。 仮パラメータthisC型の自己参照を表しています。これは、存在する場合は常にメソッド・ハンドル呼出しの先頭の引数になります。 (一部のprotectedメンバーでは、thisの型がルックアップ・クラスに制限される場合があります。下記を参照してください。) 名前argは、メソッド・ハンドルのほかのすべての引数を表しています。 Core Reflection APIのコード例に含まれる名前thisOrNullは、アクセス対象のメソッドやフィールドがstaticの場合はnull参照を表し、それ以外の場合はthisを表します。 aMethodaFieldおよびaConstructorの名前は、Cに宣言された特定のメンバーに対応するリフレクト・オブジェクトを表します。

findClass操作のバイトコード動作は、ldc CONSTANT_Classの場合と同様に、定数クラスのロードです。 振る舞いは、メソッド・ハンドルとしてではなく、直接Class定数として表されます。

指定されたメンバーが可変引数(つまりメソッドまたはコンストラクタ)の場合、返されるメソッド・ハンドルも可変引数になります。 その他のすべての場合、返されるメソッド・ハンドルは固定引数になります。

ディスカッション: ルックアップされたメソッド・ハンドルと基礎となるクラス・メンバーとバイトコード動作との間の等価性が、いくつかの方法で壊れることがあります。

  • Cがルックアップ・クラスのローダーからシンボルでアクセスできない場合でも、ルックアップが成功することがあります(同等のJava式やバイト・コード定数が存在しない場合でも)。
  • 同様に、TまたはMTがルックアップ・クラスのローダーからシンボルでアクセスできない場合でも、ルックアップが成功することがあります。 たとえば、MethodHandle.invokeExactMethodHandle.invokeのルックアップは、要求された型とは無関係に常に成功します。
  • セキュリティ・マネージャがインストールされている場合、さまざまな理由でルックアップが禁止される可能性があります(以下を参照)。 一方、CONSTANT_MethodHandle定数でのldc命令はセキュリティ・マネージャ・チェックされません。
  • 参照されたメソッドに「非常に多い引数」がある場合、メソッド・ハンドルの作成はIllegalArgumentExceptionで失敗することがあります。これは、メソッド・ハンドルの型が「あまりにも多くのパラメータ」を持つためです。

アクセス・チェック

アクセス・チェックは、メソッド・ハンドルの作成時にLookupのファクトリ・メソッド内で適用されます。 これが、Core Reflection APIとの重要な違いです(java.lang.reflect.Method.invokeではすべての呼出しで、すべての呼出し元に対してアクセス・チェックが実行される)。

すべてのアクセス・チェックはLookupオブジェクトから始まりますが、このオブジェクトでは、記録されているルックアップ・クラスとすべてのメソッド・ハンドル作成要求とが照合されます。 単一のLookupオブジェクトを使って任意の数のアクセス・チェック済みメソッド・ハンドルを作成できます(すべては単一のルックアップ・クラスに基づいてチェックされる)。

Lookupオブジェクトは、ほかの信頼できるコード(メタオブジェクト・プロトコルなど)と共有できます。 共有Lookupオブジェクトは、メソッド・ハンドルを作成する機能を、ルックアップ・クラスのprivateメンバーに委譲します。 特権付きコードがLookupオブジェクトを使用する場合でも、アクセス・チェックは元のルックアップ・クラスの特権に限定されます。

ルックアップが失敗することがあります。包含するクラスにルックアップ・クラスからアクセスできない、目的のクラス・メンバーが見つからない、目的のクラス・メンバーにルックアップ・クラスからアクセスできない、またはルックアップ・オブジェクトが信頼されていないためメンバーにアクセスためです。 finalフィールドに対するフィールドのsetter関数の場合、finalityは、アクセス制御の一種として扱われ、Lookup.unreflectSetterの特別なケースを除いてルックアップは失敗します。 いずれの場合も、試みられたルックアップからReflectiveOperationExceptionがスローされます。 具体的なクラスは次のいずれかになります。

  • NoSuchMethodException-要求されたメソッドが存在しない場合
  • NoSuchFieldException-要求されたフィールドが存在しない場合
  • IllegalAccessException-メンバーは存在しているが、アクセス・チェックが失敗した場合

一般に、メソッドMがメソッド・ハンドルをルックアップできる条件は、ルックアップ・クラスがMへの呼出しをコンパイル、検証、解決できる条件ほど制限的ではありません。 JVMがNoSuchMethodErrorなどの例外をスローするとき、メソッド・ハンドル・ルックアップは一般にNoSuchMethodExceptionなどの対応するチェック例外をスローします。 また、ルックアップの結果実行されるメソッド・ハンドル呼出しの効果は、コンパイル、検証および解決されたM呼出しを実行するのとまったく同じです。 フィールドとコンストラクタについても同じことが言えます。

ディスカッション: アクセス・チェックは、名前付きのリフレクトされたメソッド、コンストラクタ、およびフィールドにのみ適用されます。 MethodHandle.asTypeなど、他のメソッド・ハンドル作成メソッドは、アクセス・チェックを必要とせず、Lookupオブジェクトから独立して使用されます。

目的のメンバーがprotectedの場合は、通常のJVMルールが適用されます。たとえば、ルックアップ・クラスが目的のメンバーと同じパッケージ内に存在する必要があるという要件や、そのメンバーを継承する必要があります。 (『Java Virtual Machine Specification』のセクション4.9.2、5.4.3.5、および6.4を参照してください。) また、目的のメンバーが別のパッケージ内にある非staticフィールドまたはメソッドである場合、結果となるメソッド・ハンドルはルックアップ・クラスまたはそのいずれかのサブクラスのオブジェクトにしか適用されない可能性があります。 この要件は、先頭のthisパラメータの型をC (必ずルックアップ・クラスのスーパー・クラスになる)からルックアップ・クラス自体にナロー変換することで強制されます。

JVMは同様の要件をinvokespecial命令に適用します(レシーバ引数が解決済メソッドおよび現在のクラスに一致する必要がある)。 さらにこの要件は、先頭パラメータの型を結果のメソッド・ハンドルにナロー変換することで適用されます。 (『Java Virtual Machine Specification』のセクション4.10.1.9を参照してください。)

JVMは、コンストラクタおよびstaticイニシャライザ・ブロックを、特殊な名前("<init>""<clinit>")を持つ内部メソッドとして表します。 呼出し命令の内部構文は、そのような内部メソッドを通常のメソッドのように参照することを許可しますが、JVMバイトコード・ベリファイアはそれらを拒否します。 そのような内部メソッドをルックアップはNoSuchMethodExceptionを生成します。

ネストしたタイプ間の関係がNestHost属性とNestMembers属性の(Java Virtual Machine仕様、4.7.28および4.7.29セクションを参照してください)を介して直接表現される場合、関連付けられているLookupオブジェクトはルックアップ・クラスおよびそのすべてのネストされた(Class.getNestHostを参照してください)への直接アクセスを提供します。 それ以外の場合、ネストされたクラス間のアクセスは、同じネスト内の別のクラスのprivateメソッドにアクセスするラッパー・メソッドを作成するJavaコンパイラによって取得されます。 たとえば、ネストされたクラスC.Dはほかの関連クラス(CC.D.EC.Bなど)の内部のprivateメンバーにアクセスできますが、Javaコンパイラがそれらの関連クラス内でラッパー・メソッドを生成しなければいけない可能性があります。 このような場合、C.E上のLookupオブジェクトはそのプライベート・メンバーにアクセスできません。 この制限の回避方法の1つがLookup.inメソッドであり、これを使うことで、特権レベルを特別に上げることなくC.Eのルックアップをそうしたほかのクラスのいずれかのルックアップに変換できます。

指定されたルックアップ・オフセットに許可されるアクセスは、そのlookupModesセットに基づいて、ルックアップ・クラスから通常アクセスできるメンバー・サブセットに制限される場合があります。 たとえば、publicLookupメソッドは、エクスポートされたパッケージのパブリック・クラスのパブリック・メンバーにのみアクセスできるルックアップ・オブジェクトを生成します。 呼出し元依存メソッドlookupは、サポートされているすべてのバイトコード動作をエミュレートする、呼出し元クラスに関連するあらゆる機能を持つルックアップ・オブジェクトを生成します。 また、Lookup.inメソッドは元のルックアップ・オブジェクトよりアクセス・モードが少ないルックアップ・オブジェクトを生成できます。

プライベート・アクセスとモジュール・アクセスについての説明:そのルックアップ・モードprivateメンバー(ネストのプライベート・メンバーを含む)へのアクセスの可能性が含まれていると、参照にはプライベート・アクセスがあると呼びます。 ドキュメント内の関連メソッドに記述されているように、privateアクセスを持つルックアップのみが次の機能を持ちます。

同様に、モジュール・アクセスを持つ参照では、元の参照作成者が参照クラスと同じモジュール内のメンバーであることが保証されます。

プライベートおよびモジュールへのアクセスは、独立して決定されるモードであり、参照には両方、またはどちらもない可能性があります。 両方のアクセス・モードを持つ参照は、「完全な権限アクセス」と言われます。 このような参照には、次の追加機能があります:

  • 呼出し元依存メソッド(Class.forNameなど)を呼び出すメソッド・ハンドルを作成する

これらのことが許可されるのは、privateアクセスを持つルックアップ・オブジェクトから元のクラスまで安全にたどることができ、そのバイトコード動作およびJava言語アクセス権をメソッド・ハンドルが確実に判断してエミュレートできるという事実の結果です。

モジュール間参照

あるモジュールM1の参照クラスが別のモジュールM2にあるクラスにアクセスする場合、アクセス・モード・ビットの範囲を超えて余分なアクセス・チェックが実行されます。 PUBLICモードのLookupおよびM1の参照クラスでは、M2M1に対して読取り可能である場合、およびタイプがM1以上にエクスポートされるM2のパッケージ内にある場合、M2のパブリック・タイプにアクセスできます。

C上のLookupでは、Lookup.inおよびMethodHandles.privateLookupInメソッドを介してターゲット・クラスに「テレ・ポート」を実行することもできます。 モジュール間でのポートレット化では、前のルックアップ・クラスとして元の参照クラスが常に記録され、MODULEアクセス権が削除されます。 ターゲット・クラスがルックアップ・クラスCと同じモジュール内にある場合、そのターゲット・クラスは新しいルックアップ・クラスになり、以前のルックアップ・クラスに変更はありません。 ターゲット・クラスがM1 (Cのモジュール)とは異なるモジュールにある場合は、Cが新しい以前の参照クラスになり、ターゲット・クラスが新しい参照クラスになります。 その場合、M0に以前のルックアップ・クラスがすでに存在し、M1M2と異なる場合は、結果のルックアップがすべての権限をドロップします。 次に例を示します。

 
 Lookup lookup = MethodHandles.lookup();   // in class C
 Lookup lookup2 = lookup.in(D.class);
 MethodHandle mh = lookup2.findStatic(E.class, "m", MT);
 

MethodHandles.lookup()ファクトリ・メソッドにより、nullの前のルックアップ・クラスを持つLookupオブジェクトが生成されます。lookup.in(D.class)は、クラスClookupを、権限を昇格させずにDクラスに変換します。 CDが同じモジュールの場合、lookup2Dを新しい参照クラスとして記録し、元のlookupと同じ前の参照クラスを維持します。存在しない場合は、nullになります。

あるネストされたクラスから別のネストされたクラスへのLookupテレ・ポートを実行すると、PRIVATEアクセス権が削除されます。 あるパッケージのクラスから別のパッケージへのLookupテレ・ポートを実行すると、PACKAGEにアクセスできなくなります。 あるモジュールのクラスから別のモジュールへのLookupポートが提供されると、MODULEアクセス権が切断されます。 モジュール間のテレティングでは、新しいルックアップ・クラスのモジュールと古いルックアップ・クラスのモジュールの両方から、エクスポートされていないクラスにアクセスする機能をドロップします。そうすると、LookupではPUBLICアクセスのみが可能になります。 Lookupは、参照クラスのモジュール内のクラスおよび前のクラス参照のモジュールに電話をかけて移動できます。 モジュール間の通信は、アクセス権を減らすことのみができますが、増やすことはできません。 3つ目のモジュールに通信している場合は、すべてのアクセスを削除します。

前述の例では、CDが異なるモジュールにある場合、lookup2Dをその参照クラスとして記録し、lookup2にはPUBLICアクセスのみがあります。lookup2は、C 'モジュールおよびD'モジュールの他のクラスへの通信を行えます。 Eクラスが3番目のモジュールにある場合、lookup2.in(E.class)はアクセスなしでELookupを作成し、lookup2の参照クラスDは以前の参照クラスとして記録されます。

モジュール間の通信によって、参照クラスと前の参照クラスの両方が(下記参照)に同等にアクセスできるパブリック・タイプにアクセスが制限されます。

参照クラスがT「深い反射」を実行できる場合、MethodHandles.privateLookupIn(T.class, lookup)を使用して、CクラスからTクラスへのlookupの通信を行い、「プライベート・アクセス」との新しいLookupを作成できます。 lookupprivateLookupInをコールするには、MODULEおよびPRIVATEアクセス権が必要です。 モジュールM1C上でのlookupは、M1内のすべてのクラスに対してディープ・リフレクションを実行できます。 TM1に含まれる場合、privateLookupInでは、完全な機能を備えたT上に新しいLookupが生成されます。 Cでのlookupは、M1M2M2 opensM1を含むパッケージを読み取る場合に、別のモジュールM2Tをさらに深くリフレクションすることもできます。 T が新しい参照クラスになり、Cが新しい以前の参照クラスになり、MODULEのアクセス権が結果のLookupから削除されます。 結果のLookupを使用すると、Lookup::inをコールして、別の参照クラスにメンバー参照またはテレ・ポートを実行できます。 ただし、MODULEアクセス権がないため、privateLookupInをコールして別のプライベートLookupを取得するためには使用できません。

モジュール間アクセス・チェック

PUBLICを含むLookupまたはUNCONDITIONALモードを使用すると、モジュール間アクセスが可能になります。 アクセス・チェックは、参照クラスと前の参照クラス(存在する場合)の両方に対して実行されます。

UNCONDITIONALモードのLookupでは、すべてのモジュールのパブリック・タイプは「無条件でエクスポート」のパッケージの中にアクセスできます。

M1LCLookupに以前の参照クラスがない場合、PUBLICモードで参照すると、M1で読取り可能なモジュール内のすべてのパブリック・タイプにアクセスでき、タイプは少なくともM1にエクスポートされるパッケージ内にあります。

M1LCLCに以前の参照クラスM0の前の参照クラスPLCがある場合、PUBLICモードでの参照は、PUBLICモードで参照すると、M0からアクセス可能なすべてのパブリック・タイプを使用して、M1でアクセスできるすべてのパブリック・タイプの共通部分にアクセスできます。 M0M1を読み取るため、アクセス可能なタイプのセットには次のものがあります:

次のパッケージのパブリック・タイプには、参照クラスと前の参照クラスからアクセスできます。
M0およびM1に均等にアクセス可能な型
M1からの無条件エクスポートのパッケージ
M1M0を読み込む場合、M0から無条件エクスポート・パッケージをエクスポート
M0M1の両方がM2を読み上げた場合、第3のモジュールM2から無条件エクスポートのパッケージをエクスポート
レイヤー化されたエクスポート済パッケージ: M1からM0
M1M0を読み取った場合に、M0からM1に並列エクスポートされたパッケージ
M0M1の両方がM2を読む場合、3番目のモジュールM2からM0M1の両方にレイヤー化されたエクスポートされたパッケージ

アクセス・モード

次の表に、ファクトリまたは変換のいずれかのメソッドによって生成されるLookupのアクセス・モードを示します:
アクセス・モード・サマリー
オブジェクトの参照 protected private package module public
CCL = MethodHandles.lookup() PRO PRI PAC MOD 1R
CL.in(C1)同じパッケージ PAC MOD 1R
CL.in(C1)同じモジュール MOD 1R
CL.in(D)の異なるモジュール 2R
モジュールにCL.in(D).in(C)ホップ・バック 2R
PRI1 = privateLookupIn(C1,CL) PRO PRI PAC MOD 1R
PRI1a = privateLookupIn(C,PRI1) PRO PRI PAC MOD 1R
PRI1.in(C1)同じパッケージ PAC MOD 1R
PRI1.in(C1)パッケージが異なります MOD 1R
PRI1.in(D)の異なるモジュール 2R
PRI1.dropLookupMode(PROTECTED) PRI PAC MOD 1R
PRI1.dropLookupMode(PRIVATE) PAC MOD 1R
PRI1.dropLookupMode(PACKAGE) MOD 1R
PRI1.dropLookupMode(MODULE) 1R
PRI1.dropLookupMode(PUBLIC) なし
PRI2 = privateLookupIn(D,CL) PRO PRI PAC 2R
privateLookupIn(D,PRI1) PRO PRI PAC 2R
privateLookupIn(C,PRI2)は失敗 IAE
PRI2.in(D2)同じパッケージ PAC 2R
PRI2.in(D2)パッケージが異なります 2R
モジュールにPRI2.in(C1)ホップ・バック 2R
PRI2.in(E)ホップから3番目のモジュール なし
PRI2.dropLookupMode(PROTECTED) PRI PAC 2R
PRI2.dropLookupMode(PRIVATE) PAC 2R
PRI2.dropLookupMode(PACKAGE) 2R
PRI2.dropLookupMode(MODULE) 2R
PRI2.dropLookupMode(PUBLIC) なし
CL.dropLookupMode(PROTECTED) PRI PAC MOD 1R
CL.dropLookupMode(PRIVATE) PAC MOD 1R
CL.dropLookupMode(PACKAGE) MOD 1R
CL.dropLookupMode(MODULE) 1R
CL.dropLookupMode(PUBLIC) なし
PUB = publicLookup() U
PUB.in(D)の異なるモジュール U
PUB.in(D).in(E) 3番目のモジュール U
PUB.dropLookupMode(UNCONDITIONAL) なし
privateLookupIn(C1,PUB)は失敗 IAE
ANY.in(X)(アクセスできないXの場合) なし

ノート:

  • CクラスとC1クラスは、モジュールM1内にありますが、DD2はモジュールM2で、EはモジュールM3にあります。 X は、参照がアクセス不可能なクラスを探します。 ANY は、サンプル・ルックアップの表します。
  • PRO は、PROTECTEDビットがセットされていることを示し、PRIは、PRIVATEビットがセットされていることを示し、PACは、PACKAGEビットがセットされていることを示し、MODは、MODULEビットがセットされていることを示し、1Rおよび2RPUBLICビット・セットを示し、UUNCONDITIONALビット・セットを示し、IAEは、IllegalAccessExceptionがスローされたことを示します。
  • パブリック・アクセスには、次の3種類があります:
    • 無条件(U): ルックアップは読みやすくなっています。 ルックアップにnull前のルックアップ・クラスがある場合。
    • one-module-reads (1R): モジュール・アクセス・チェックは、参照クラスに対して実行します。 ルックアップにnull前のルックアップ・クラスがある場合。
    • two-module-reads (2R): モジュール・アクセス・チェックは、参照クラスおよび前の参照クラスについて実行されます。 ルックアップに、現在のルックアップ・クラスとは異なるモジュール内にあるnull以外の前のルックアップ・クラスが含まれています。
  • 3つ目のモジュールに到達しようとすると、すべてのアクセスが失われます。
  • Lookup::inでは、ターゲット・クラスXにアクセスできない場合、すべてのアクセス・モードが削除されます。

セキュリティ・マネージャとの対話

バイト・コード命令は関連クラス・ローダー内のクラスしか参照できませんが、このAPIでは、Classオブジェクトへの参照が使用可能であるかぎり、任意のクラス内のメソッドを検索できます。 そのようなクロスローダー参照は、Core Reflection APIでも可能ですが、invokestaticgetfieldなどのバイト・コード命令では不可能です。 アプリケーション内でそのようなクロスローダー参照をチェックできるようにするためのセキュリティ・マネージャAPIが存在します。 それらのチェックは、MethodHandles.Lookup APIと(Class上に存在する) Core Reflection APIの両方に適用されます。

セキュリティ・マネージャが存在する場合、メンバーおよびクラスのルックアップは追加検査の対象となります。 セキュリティ・マネージャに対して1回から3回の呼出しが行われます。 これらの呼出しのいずれも、SecurityExceptionをスローすることでアクセスを拒否できます。 smgrをセキュリティ・マネージャとして、lookcを現在のルックアップ・オブジェクトのルックアップ・クラスとして、refcをメンバーを検索する包含クラスとして、defcをメンバーが実際に定義されるクラスとして定義してください。 (クラスまたは他の型がアクセスされている場合、refcおよびdefcの値はクラスそのものです。) 現在の参照オブジェクトに「完全な権限アクセス」が含まれない場合、lookc値は「存在しない」と定義されます。 次のルールに従って呼出しが行われます。

  • ステップ1: lookcが存在しない場合、またはそのクラス・ローダーがrefcのクラス・ローダーと同じでもその祖先でもない場合は、smgr.checkPackageAccess(refcPkg)が呼び出されます(refcPkgrefcのパッケージ)。
  • ステップ2a: 取り出されたメンバーが公開されておらず、lookcが存在しない場合は、RuntimePermission("accessDeclaredMembers")を含むsmgr.checkPermissionが呼び出されます。
  • ステップ2b: 取得したクラスにnullクラス・ローダーがあり、lookcが存在しない場合は、RuntimePermission("getClassLoader")を含むsmgr.checkPermissionが呼び出されます。
  • ステップ3: 取得されるメンバーがpublicでなく、lookcが存在せず、defcrefcが異なる場合は、smgr.checkPackageAccess(defcPkg)が呼び出されます(defcPkgdefcのパッケージ)。
セキュリティ・チェックは他のアクセス・チェックを合格した後に実行されます。 したがって、上記の規則は、パブリックであるメンバーまたはクラス、またはそのメンバーまたはクラスにアクセスするためのアクセス権を持つ参照クラスからアクセスされていることを前提としています。

セキュリティ・マネージャが存在し、現在の参照オブジェクトに「完全な権限アクセス」がない場合、defineClassでは、RuntimePermission("defineClass")を使用してsmgr.checkPermissionをコールします。

呼出し元依存メソッド

少数のJavaメソッドに、呼出し元依存性という特殊なプロパティがあります。 呼出し元依存メソッドは、その直接の呼出し元の識別情報によって異なる動作をする可能性があります。

呼出し元依存メソッドのメソッド・ハンドルが要求された場合は、バイトコード動作の一般ルールが適用されますが、ルックアップ・クラスは特別な方法で考慮されます。 結果のメソッド・ハンドルはルックアップ・クラスに含まれている命令から呼び出されたように動作し、呼出し元依存メソッドはルックアップ・クラスを検出します。 (一方、メソッド・ハンドルのインボーカは無視されます。) したがって、呼出し元依存メソッドの場合は、ルックアップ・クラスごとにメソッド・ハンドルの動作が異なる可能性があります。

ルックアップ・オブジェクトがpublicLookup()の場合や、「完全な権限アクセス」を使用しないその他のルックアップ・オブジェクトの場合は、ルックアップ・クラスが無視されます。 そのような場合、呼出し元依存メソッド・ハンドルを作成できず、アクセスは禁止され、ルックアップはIllegalAccessExceptionで失敗します。

ディスカッション: たとえば、呼出し元依存メソッドClass.forName(x)は、それを呼び出すクラスのクラス・ローダーに応じて、返されるクラスを異なったり、スローされる例外が異なったりする可能性があります。 Class.forNameのpublicルックアップは失敗します。そのバイトコード動作を判別するための妥当な方法がないためです。

広範囲な共有のためにメソッド・ハンドルをキャッシュするアプリケーションの場合は、publicLookup()を使用してメソッド・ハンドルを作成することをお薦めします。 Class.forNameのルックアップがある場合、それは失敗し、アプリケーションはその場合に適切なアクションを取る必要があります。 たとえば、後のルックアップ(おそらくブートストラップ・メソッドの呼び出し中)が呼出し元固有の識別情報を組み込むことで、メソッドをアクセス可能にするアクションです。

関数MethodHandles.lookupは呼出し元依存なので、ルックアップ用の安全な基盤が存在できます。 JSR 292 API内の他のほとんどすべてのメソッドはルックアップ・オブジェクトに依存してアクセス要求をチェックします。

  • フィールドのサマリー

    フィールド 
    修飾子と型 フィールド 説明
    static int MODULE
    moduleのアクセスを表すシングルトン・マスクで、lookupModesの結果に影響する可能性があります。
    static int PACKAGE
    packageアクセス(デフォルト・アクセス)を表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。
    static int PRIVATE
    privateアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。
    static int PROTECTED
    protectedアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。
    static int PUBLIC
    publicアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。
    static int UNCONDITIONAL
    unconditionalアクセスを表す単一ビット・マスクで、lookupModesの結果に寄与する可能性があります。
  • メソッドのサマリー

    修飾子と型 メソッド 説明
    Class<?> accessClass​(Class<?> targetClass)
    このLookupオブジェクトによって定義されたルックアップ・コンテキストからクラスにアクセスできるかどうかを判定します。
    MethodHandle bind​(Object receiver, String name, MethodType type)
    非staticメソッドの早期バインド・メソッド・ハンドルを生成します。
    Class<?> defineClass​(byte[] bytes)
    クラスを同じクラス・ローダーと同じランタイム・パッケージに定義し、「保護ドメイン」をこのルックアップ「ルックアップ・クラス」として定義します。
    MethodHandles.Lookup dropLookupMode​(int modeToDrop)
    このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。
    Class<?> findClass​(String targetName)
    このLookupオブジェクト「解決された場合」によってldcの命令で定義された参照コンテキストから名前でクラスを検索します。
    MethodHandle findConstructor​(Class<?> refc, MethodType type)
    指定された型のコンストラクタを使ってオブジェクトの作成と初期化を行うメソッド・ハンドルを生成します。
    MethodHandle findGetter​(Class<?> refc, String name, Class<?> type)
    非staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。
    MethodHandle findSetter​(Class<?> refc, String name, Class<?> type)
    非staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。
    MethodHandle findSpecial​(Class<?> refc, String name, MethodType type, Class<?> specialCaller)
    仮想メソッドの早期にバインドされるメソッド・ハンドルを生成します。
    MethodHandle findStatic​(Class<?> refc, String name, MethodType type)
    staticメソッドのメソッド・ハンドルを生成します。
    MethodHandle findStaticGetter​(Class<?> refc, String name, Class<?> type)
    staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。
    MethodHandle findStaticSetter​(Class<?> refc, String name, Class<?> type)
    staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。
    VarHandle findStaticVarHandle​(Class<?> decl, String name, Class<?> type)
    declのクラスで宣言された型typeの静的フィールドnameへのアクセスを提供するVarHandleを生成します。
    VarHandle findVarHandle​(Class<?> recv, String name, Class<?> type)
    recvのクラスで宣言された型typeの非静的フィールドnameへのアクセスを提供するVarHandleを生成します。
    MethodHandle findVirtual​(Class<?> refc, String name, MethodType type)
    仮想メソッドのメソッド・ハンドルを生成します。
    boolean hasFullPrivilegeAccess()
    この参照に「完全な権限アクセス」がある場合、つまりtrueを返します。
    boolean hasPrivateAccess()
    Deprecated.
    このメソッドは、当初は、完全な権限アクセスを意味するPRIVATEアクセスをテストするように設計されましたが、MODULEアクセスはPRIVATEアクセスから独立しているためです。
    MethodHandles.Lookup in​(Class<?> requestedLookupClass)
    指定された新しいルックアップ・クラスでルックアップを作成します。
    Class<?> lookupClass()
    ルックアップを実行しているクラスを示します。
    int lookupModes()
    このルックアップ・オブジェクトがどのアクセス保護クラスのメンバーを生成できるかを示します。
    Class<?> previousLookupClass()
    この参照オブジェクトが以前に電話をかけていた別のモジュール、またはnullで参照区分を報告します。
    MethodHandleInfo revealDirect​(MethodHandle target)
    この参照オブジェクトまたは類似のオブジェクトによって作成された直接メソッド・ハンドルを解読します。
    String toString()
    ルックアップの実行元となるクラスの名前を表示します。
    MethodHandle unreflect​(Method m)
    ルックアップ・クラスがアクセス権を持つ場合に、mへの直接メソッド・ハンドルを作成します。
    MethodHandle unreflectConstructor​(Constructor<?> c)
    リフレクトされたコンストラクタのメソッド・ハンドルを生成します。
    MethodHandle unreflectGetter​(Field f)
    リフレクトされたフィールドに対する読取りアクセス権を提供するメソッド・ハンドルを生成します。
    MethodHandle unreflectSetter​(Field f)
    リフレクトされたフィールドに対する書込みアクセス権を提供するメソッド・ハンドルを生成します。
    MethodHandle unreflectSpecial​(Method m, Class<?> specialCaller)
    リフレクトされたメソッドのメソッド・ハンドルを生成します。
    VarHandle unreflectVarHandle​(Field f)
    クラスRで宣言されたT型の反映されたフィールドfへのアクセスを提供するVarHandleを生成します。

    クラス java.lang.Objectで宣言されたメソッド

    cloneequalsfinalizegetClasshashCodenotifynotifyAllwaitwaitwait
  • フィールド詳細

    • PUBLIC

      public static final int PUBLIC
      publicアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。 0x01はたまたま、public 修飾子ビットの値と同じになっています。

      この参照モードのLookupでは、「ルックアップ・クラス」および「前のルックアップ・クラス」(存在する場合)について、モジュール間アクセス・チェックが実行されます。

      関連項目:
      定数フィールド値
    • PRIVATE

      public static final int PRIVATE
      privateアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。 0x02はたまたま、private 修飾子ビットの値と同じになっています。
      関連項目:
      定数フィールド値
    • PROTECTED

      public static final int PROTECTED
      protectedアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。 0x04はたまたま、protected 修飾子ビットの値と同じになっています。
      関連項目:
      定数フィールド値
    • PACKAGE

      public static final int PACKAGE
      packageアクセス(デフォルト・アクセス)を表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。 値は0x08ですが、これは、特定のどの修飾子ビットにも、意味のあるかたちでは対応しません。
      関連項目:
      定数フィールド値
    • MODULE

      public static final int MODULE
      moduleのアクセスを表すシングルトン・マスクで、lookupModesの結果に影響する可能性があります。 値は0x10です。これは特定の「修飾子ビット」には意味がありません。 PUBLIC修飾子ビットと組み合わせて、このルックアップ・モードを持つLookupは、ルックアップ・クラスのモジュール内のすべてのパブリック型と、他のモジュールによってルックアップ・クラスのモジュールにエクスポートされたパブリック型にアクセスできます。

      この参照モードが設定されている場合、「前のルックアップ・クラス」は常にnullです。

      導入されたバージョン:
      9
      関連項目:
      定数フィールド値
    • UNCONDITIONAL

      public static final int UNCONDITIONAL
      unconditionalアクセスを表す単一ビット・マスクで、lookupModesの結果に寄与する可能性があります。 値は0x20です。これは特定の「修飾子ビット」には意味がありません。 このルックアップ・モードのLookupreadabilityを想定しています。 この参照モードでは、タイプがexported unconditionallyであるパッケージ内にある場合、すべてのモジュールのパブリック・タイプのすべてのパブリック・メンバーにアクセスできます。

      この参照モードが設定されている場合、「前のルックアップ・クラス」は常にnullです。

      導入されたバージョン:
      9
      関連項目:
      MethodHandles.publicLookup(), 「定数フィールド値」
  • メソッドの詳細

    • lookupClass

      public Class<?> lookupClass()
      ルックアップを実行しているクラスを示します。 可視性やアクセス権のチェックが実行されるのは、このクラスに対してです。

      この参照オブジェクトに「前のルックアップ・クラス」がある場合、アクセス・チェックは参照クラスおよび前の参照クラスの両方に対して実行されます。

      このクラスは最大レベルのアクセス権を暗黙的に示しますが、非publicメンバーにアクセスできるかどうかを制御するビット・マスクlookupModesにより、アクセス権がさらに制限される可能性もあります。

      戻り値:
      ルックアップ・クラス、これのためにこのルックアップ・オブジェクトはメンバーを探す
      関連項目:
      モジュール間参照
    • previousLookupClass

      public Class<?> previousLookupClass()
      この参照オブジェクトが以前に電話をかけていた別のモジュール、またはnullで参照区分を報告します。

      ファクトリ・メソッドで生成されるlookup()publicLookup()メソッドなどのLookupオブジェクトには、nullの前の参照クラスがあります。 Lookupオブジェクトにnull以外の以前の参照クラスがあります。この参照が、あるモジュールの古い参照クラスから別のモジュールの新しい参照クラスに移植されたときです。

      戻り値:
      この参照オブジェクトが以前に通信したことのある他のモジュール内の参照クラスまたはnull
      導入されたバージョン:
      14
      関連項目:
      in(Class), MethodHandles.privateLookupIn(Class, Lookup), 「モジュール間参照」
    • lookupModes

      public int lookupModes()
      このルックアップ・オブジェクトがどのアクセス保護クラスのメンバーを生成できるかを示します。 その結果、ビットPUBLIC (0x01)「プライベート(0x02)」「保護された(0x04)」「パッケージ(0x08)」MODULE (0x10)、およびUNCONDITIONAL (0x20)のビット・マスクが生成されます。

      「呼び出し元クラス」の新しく作成された検索オブジェクトには、UNCONDITIONALを除くすべての可能なビットが設定されています。 以前のルックアップ・オブジェクトから作成された新しいルックアップ・クラス上のルックアップ・オブジェクトでは、いくつかのモード・ビットがゼロに設定されている可能性があります。 また、モード・ビットは「直接クリア」できます。 クリアされると、モード・ビットはダウングレードされたルックアップ・オブジェクトからリストアできません。 その目的は、新しいルックアップ・オブジェクト経由でのアクセスを制限し、元のルックアップ・オブジェクトと新しいルックアップ・クラスの両方から到達可能な名前だけにアクセスできるようにすることです。

      戻り値:
      ルックアップ・モード、このルックアップ・オブジェクトによって実行されるアクセスの種類を制限する
      関連項目:
      in(java.lang.Class<?>), dropLookupMode(int)
    • in

      public MethodHandles.Lookup in​(Class<?> requestedLookupClass)
      指定された新しいルックアップ・クラスでルックアップを作成します。 結果となるオブジェクトは、指定されたクラスを自身のlookupClassとして報告します。

      ただし、結果となるLookupオブジェクトは、元のオブジェクトと同等以下のアクセス機能しか持たないことが保証されます。 具体的には、アクセス機能が次のように失われる可能性があります。

      • 新しいルックアップ・クラスが古いクラスとは別のモジュールにある場合、つまりMODULEアクセスが失われる場合。
      • 新しいルックアップ・クラスが古い保護されているパッケージとは異なるパッケージにある場合、およびデフォルトの(package)メンバーにはアクセスできません。つまり、PROTECTEDおよびPACKAGEアクセスは失われます。
      • 新しいルックアップ・クラスが古いルックアップ・メンバーと同じパッケージ・メンバー内にない場合、プライベート・メンバーにはアクセスできず、保護されたメンバーは継承によってアクセスできません。つまり、PRIVATEのアクセスが失われます。 (パッケージ共有のため、protectedメンバーに引き続きアクセスできる場合もあります。)
      • 新しい参照クラスがこの参照に対して「アクセシビリティ」ではない場合、パブリック・メンバーでなく、すべてのアクセス・モードが失われるなど、メンバーにアクセスすることはできません。
      • 新規参照クラスの場合、古い参照クラスと以前の参照クラスはすべて異なるモジュールにあります。つまり、3番目のモジュールに対するテレ・ポートでは、すべてのアクセス・モードが失われます。

      以前の新規ルックアップ・クラスは次のように選択されます:

      • 新しい参照オブジェクトにUNCONDITIONALビットがある場合、以前の新しい参照クラスはnullです。
      • 新しい参照クラスが古い参照クラスと同じモジュールにある場合、以前の新しい参照クラスは以前の古い参照クラスになります。
      • 新しい参照クラスが古い参照クラスと異なるモジュールにある場合、新しい以前の参照クラスは古い参照クラスとなります。

      クラス(findClass(java.lang.String)呼び出し中に使用される)をロードするために結果として得られるルックアップ機能は、ルックアップ・クラスのローダーによって決定されます。このローダーは、この操作によって変更される可能性があります。

      パラメータ:
      requestedLookupClass - 新しいルックアップ・オブジェクト用に要求されるルックアップ・クラス
      戻り値:
      目的のルックアップ・クラスを報告するルックアップ・オブジェクト、または変更がなければ同じオブジェクト
      例外:
      IllegalArgumentException - requestedLookupClassがプリミティブ・タイプ、voidまたは配列クラスの場合
      NullPointerException - 引数がnullの場合
      関連項目:
      accessClass(Class), 「モジュール間参照」
    • dropLookupMode

      public MethodHandles.Lookup dropLookupMode​(int modeToDrop)
      このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。 ドロップするルックアップ・モードは、PUBLICMODULEPACKAGEPROTECTEDまたはPRIVATEのいずれかです。 PROTECTEDは常に削除されるため、作成される参照モードにはこのアクセス機能がありません。 PACKAGEを削除すると、結果のルックアップにはPACKAGEまたはPRIVATEアクセスがありません。 MODULEをドロップすると、結果のルックアップにはMODULEPACKAGE、またはPRIVATEアクセスがありません。 PUBLICがドロップされた場合、結果のルックアップにはアクセス権がありません。 UNCONDITIONALがドロップされると、結果のルックアップにアクセスできなくなります。
      APIのノート:
      PRIVATEモードではなくPACKAGEを参照すると、「プライベート・アクセス」を提供せずに、参照クラスのパッケージ内でパブリックでないアクセスを安全に委任できます。 PACKAGEモードではなくMODULEを参照すると、パッケージ・アクセス権を付与せずに、参照クラスのモジュール内でPUBLICアクセスを安全に委任できます。 「前のルックアップ・クラス」 (およびPUBLICMODULEモードではありません)を使用した参照では、参照クラスのモジュールと以前の参照クラスのモジュールの両方からアクセス可能なパブリック・クラスに安全にアクセス権を委任できます。
      パラメータ:
      modeToDrop - ルックアップ・モードをドロップ
      戻り値:
      示されたモードを持たない参照オブジェクト、または変更がなければ同じオブジェクト
      例外:
      IllegalArgumentException - modeToDropPUBLICMODULEPACKAGEPROTECTEDPRIVATEまたはUNCONDITIONALのいずれかでない場合
      導入されたバージョン:
      9
      関連項目:
      MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
    • defineClass

      public Class<?> defineClass​(byte[] bytes) throws IllegalAccessException
      クラスを同じクラス・ローダーと同じランタイム・パッケージに定義し、「保護ドメイン」をこのルックアップ「ルックアップ・クラス」として定義します。

      このルックアップの「ルックアップ・モード」には、PACKAGEアクセスが含まれている必要があります。デフォルトでは、(package)メンバーはクラスにアクセスできます。 PACKAGEルックアップ・モードは、ルックアップ・オブジェクトがランタイム・パッケージ(または適切に特権コードによって作成されたルックアップから、ランタイム・パッケージ内のターゲット・クラスに派生)の呼び出し側によって作成されたことを認証する役割を果たします。

      bytesパラメータは、ルックアップ・クラスと同じパッケージ内のクラス名を持つ有効なクラス・ファイル(「Java Virtual Machine仕様」で定義されている)のクラス・バイトです。

      このメソッドは、クラス初期化子を実行しません。 クラス初期化子は、「Java言語仕様」のセクション12.4で詳しく説明するように、後で実行することができます。

      セキュリティ・マネージャが存在し、この参照に「完全な権限アクセス」がない場合、checkPermissionメソッドが最初にコールされてRuntimePermission("defineClass")がチェックされます。

      パラメータ:
      bytes - クラス・バイト
      戻り値:
      クラスのClassオブジェクト
      例外:
      IllegalArgumentException - バイトはルックアップ・クラスとは異なるパッケージ内のクラス用です
      IllegalAccessException - このルックアップにPACKAGEアクセスがない場合
      LinkageError - クラスが不正な形式(ClassFormatError)であるか、(VerifyError)であるか、(VerifyError)であるか、すでに定義されているか、別のリンク・エラーが発生した場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - bytesnullの場合
      導入されたバージョン:
      9
      関連項目:
      MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup), dropLookupMode(int), ClassLoader.defineClass(String,byte[],int,int,ProtectionDomain)
    • toString

      public String toString()
      参照の元であるクラスの名前が表示されます。この名前の後には、"/"が続き、「前のルックアップ・クラス」の名前(存在する場合)が表示されます。 (名前はClass.getNameから報告されるものです。) このルックアップに許可されるアクセスに制限がある場合、そのことを示すために、スラッシュとキーワードで構成される接尾辞がクラス名に追加されます。 キーワードは許可される最強のアクセスを表しており、次のように選択されます。
      • アクセスが一切許可されない場合、接尾辞は「/noaccess」になります。
      • 無条件アクセスのみが許可される場合、サフィクスは"/publicLookup"です。
      • エクスポートされたパッケージの型へのパブリック・アクセスのみが許可されている場合、サフィクスは"/public"です。
      • パブリック・アクセスとモジュール・アクセスのみが許可されている場合、サフィクスは"/module"です。
      • パブリック・アクセスおよびパッケージ・アクセスが許可される場合、サフィクスは"/package"です。
      • パブリック、パッケージおよびプライベート・アクセスが許可される場合、サフィクスは"/private"です。
      上記のいずれのケースも当てはまらない場合は、フル・アクセス(パブリック、モジュール、パッケージ、プライベート、および保護された)が許可されている場合があります。 この場合、接尾辞は追加されません。 これが真となるのは、もともとMethodHandles.lookupから取得されたオブジェクトの場合だけです。 Lookup.inで作成されたオブジェクトでは常にアクセスが制限され、接尾辞が表示されます。

      (protectedアクセスがprivateアクセスより強いというのは、奇妙に感じるかもしれません。 packageアクセスから独立して見た場合、protectedアクセスが最初に失われるものになりますが、それは、呼出し元と呼出し先の間に直接的なサブクラス関係が必要になるからです。)

      オーバーライド:
      toString 、クラス:  Object
      戻り値:
      このオブジェクトの文字列表現
      関連項目:
      in(java.lang.Class<?>)
    • findStatic

      public MethodHandle findStatic​(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
      staticメソッドのメソッド・ハンドルを生成します。 メソッド・ハンドルの型は、メソッドの型になります。 (staticメソッドはレシーバを取らないため、findVirtualfindSpecialのように、メソッド・ハンドルの型に追加のレシーバ引数が挿入されることはありません。) このメソッドとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。

      返されるメソッド・ハンドルの引数が可変引数になるのは、メソッドの可変引数修飾子ビット(0x0080)が設定されている場合だけです。

      返されるメソッド・ハンドルが呼び出された場合、そのメソッドのクラスは初期化されます(まだ初期化されていない場合)。

      例:

      
      import static java.lang.invoke.MethodHandles.*;
      import static java.lang.invoke.MethodType.*;
      ...
      MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
        "asList", methodType(List.class, Object[].class));
      assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
       

      パラメータ:
      refc - メソッドのアクセス元となるクラス
      name - メソッドの名前
      type - メソッドの型
      戻り値:
      目的のメソッド・ハンドル
      例外:
      NoSuchMethodException - メソッドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドがstaticでない場合、あるいはメソッドの可変引数修飾子ビットが設定されてasVarargsCollectorが失敗した場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
    • findVirtual

      public MethodHandle findVirtual​(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
      仮想メソッドのメソッド・ハンドルを生成します。 メソッド・ハンドルの型は、メソッドの型の先頭にレシーバの型(通常はrefc)を追加したものになります。 このメソッドとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。

      ハンドルが呼び出されると、最初の引数がレシーバとして扱われ、非駆動型のメソッドがディスパッチされ、どのメソッド実装を入力するかが決定されます。 プライベート・メソッドの場合、refc内の名前付きメソッドが受信側で呼び出されます。 (このディスパッチ・アクションは、invokevirtualまたはinvokeinterface命令によって実行されるアクションと同一です。)

      ルックアップ・クラスがメンバーにアクセスする完全な権限を持っている場合、最初の引数の型はrefcになります。 それ以外の場合、メンバーはprotectedである必要があり、最初の引数の型はルックアップ・クラスに制限されます。

      返されるメソッド・ハンドルの引数が可変引数になるのは、メソッドの可変引数修飾子ビット(0x0080)が設定されている場合だけです。

      invokevirtual命令とfindVirtualによって生成されるメソッド・ハンドルとの間の一般的な等価性のために、クラスがMethodHandleで名前文字列がinvokeExactまたはinvokeの場合は、結果のメソッド・ハンドルは同じtype引数のMethodHandles.exactInvokerまたはMethodHandles.invokerで生成されたものと同等です。

      クラスがVarHandleで、名前文字列がシグネチャ・ポリモーフィック・アクセス・モード・メソッドの名前に対応する場合、結果のメソッド・ハンドルは、名前文字列に対応し、同じtype引数を持つアクセス・モードでMethodHandles.varHandleInvoker(java.lang.invoke.VarHandle.AccessMode, java.lang.invoke.MethodType)によって生成されたものと同等です。

      例:

      
      import static java.lang.invoke.MethodHandles.*;
      import static java.lang.invoke.MethodType.*;
      ...
      MethodHandle MH_concat = publicLookup().findVirtual(String.class,
        "concat", methodType(String.class, String.class));
      MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,
        "hashCode", methodType(int.class));
      MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,
        "hashCode", methodType(int.class));
      assertEquals("xy", (String) MH_concat.invokeExact("x", "y"));
      assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy"));
      assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy"));
      // interface method:
      MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
        "subSequence", methodType(CharSequence.class, int.class, int.class));
      assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
      // constructor "internal method" must be accessed differently:
      MethodType MT_newString = methodType(void.class); //()V for new String()
      try { assertEquals("impossible", lookup()
              .findVirtual(String.class, "<init>", MT_newString));
       } catch (NoSuchMethodException ex) { } // OK
      MethodHandle MH_newString = publicLookup()
        .findConstructor(String.class, MT_newString);
      assertEquals("", (String) MH_newString.invokeExact());
       

      パラメータ:
      refc - メソッドのアクセス元となるクラスまたはインタフェース
      name - メソッドの名前
      type - メソッドの型(レシーバ引数は含まない)
      戻り値:
      目的のメソッド・ハンドル
      例外:
      NoSuchMethodException - メソッドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドがstatic,の場合、あるいはメソッドの可変引数修飾子ビットが設定されてasVarargsCollectorが失敗した場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
    • findConstructor

      public MethodHandle findConstructor​(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException
      指定された型のコンストラクタを使ってオブジェクトの作成と初期化を行うメソッド・ハンドルを生成します。 メソッド・ハンドルのパラメータの型はコンストラクタのパラメータの型になり、戻り値の型はコンストラクタのクラスへの参照になります。 コンストラクタとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。

      要求する型の戻り値の型はvoidでなければいけません。 (これは、JVMのコンストラクタ型記述子の扱いに準拠しています。)

      返されるメソッド・ハンドルの引数が可変引数になるのは、コンストラクタの可変引数修飾子ビット(0x0080)が設定されている場合だけです。

      返されるメソッド・ハンドルが呼び出された場合、そのコンストラクタのクラスは初期化されます(まだ初期化されていない場合)。

      例:

      
      import static java.lang.invoke.MethodHandles.*;
      import static java.lang.invoke.MethodType.*;
      ...
      MethodHandle MH_newArrayList = publicLookup().findConstructor(
        ArrayList.class, methodType(void.class, Collection.class));
      Collection orig = Arrays.asList("x", "y");
      Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
      assert(orig != copy);
      assertEquals(orig, copy);
      // a variable-arity constructor:
      MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
        ProcessBuilder.class, methodType(void.class, String[].class));
      ProcessBuilder pb = (ProcessBuilder)
        MH_newProcessBuilder.invoke("x", "y", "z");
      assertEquals("[x, y, z]", pb.command().toString());
       

      パラメータ:
      refc - メソッドのアクセス元となるクラスまたはインタフェース
      type - メソッドの型(レシーバ引数は含めず、戻り値の型はvoidにする)
      戻り値:
      目的のメソッド・ハンドル
      例外:
      NoSuchMethodException - コンストラクタが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドの可変引数修飾子ビットが設定されていてasVarargsCollectorが失敗した場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
    • findClass

      public Class<?> findClass​(String targetName) throws ClassNotFoundException, IllegalAccessException
      このLookupオブジェクト「解決された場合」によってldcの命令で定義された参照コンテキストから名前でクラスを検索します。 このような解決策は、JVMS 5.4.3.1セクションで指定されているように、クラスを検索してロードしようとし、そのクラスがこの参照オブジェクトにアクセス可能かどうかを判断します。

      ここでのルックアップ・コンテキストは、「ルックアップ・クラス」、そのクラス・ローダー、および「ルックアップ・モード」によって決定されます。

      パラメータ:
      targetName - 参照されるクラスの完全修飾名。
      戻り値:
      リクエストされたクラス。
      例外:
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      LinkageError - リンケージに失敗した場合
      ClassNotFoundException - ルックアップ・クラス・ローダーによってクラスをロードできない場合。
      IllegalAccessException - クラスにアクセスできない場合は、許可されたアクセス・モードを使用します。
      Java Virtual Machine仕様を参照してください:
      5.4.3.1 クラスおよびインタフェースの解決
      導入されたバージョン:
      9
    • accessClass

      public Class<?> accessClass​(Class<?> targetClass) throws IllegalAccessException
      このLookupオブジェクトによって定義されたルックアップ・コンテキストからクラスにアクセスできるかどうかを判定します。 クラスの静的初期化子は実行されません。

      targetClassが参照クラスと同じモジュールにある場合、その参照クラスはモジュールM1LCになり、前の参照クラスがモジュールM0またはnullにある場合、targetClassは、次のいずれかがtrueである場合にのみアクセス可能です:

      • この参照にPRIVATEアクセス権がある場合、targetClassLCの同じネストに含まれているLCまたは他のクラスです。
      • この参照にPACKAGEアクセス権がある場合、targetClassLCの同じランタイム・パッケージに含まれます。
      • この参照にMODULEアクセス権がある場合、targetClassM1の公開タイプです。
      • この参照にPUBLICアクセス権がある場合、targetClassは、以前の参照クラスが存在する場合に少なくともM0にエクスポートされるパッケージのパブリック・タイプです。それ以外の場合、targetClassM1で無条件にエクスポートされたパッケージ内のパブリック・タイプです。

      そうでない場合、この参照にUNCONDITIONALアクセス権が含まれていると、タイプが無条件でエクスポートされたパッケージの場合、この参照ではすべてのモジュールの公開タイプにアクセスできます。

      それ以外の場合、ターゲット・クラスはlookupClassと異なるモジュールにあり、この参照にPUBLICアクセスがない場合、lookupClassにはアクセスできません。

      それ以外の場合でこの参照に「前のルックアップ・クラス」が含まれない場合、M1lookupClassを含むモジュール、M2targetClassを含むモジュールであり、次の場合にのみtargetClassにアクセスできます

      • M1M2を読み取り、
      • targetClassはパブリックで、M2によって少なくともM1にエクスポートされたパッケージ内にあります。

      それ以外の場合で、この参照に「前のルックアップ・クラス」M1およびM2が以前と同様であり、M0が以前の参照クラスを含むモジュールである場合、targetClassは次のいずれかがtrueである場合にのみアクセス可能です:

      • targetClassM0にあり、M1M0を読み取り、タイプは少なくともM1にエクスポートされるパッケージ内にあります。
      • targetClassM1にあり、M0M1を読み取り、タイプは少なくともM0にエクスポートされるパッケージ内にあります。
      • targetClassは3つ目のモジュールM2に含まれ、M0M1は両方ともM2を読み取り、タイプは少なくともM0M2の両方にエクスポートされるパッケージに含まれます。

      それ以外の場合、targetClassにはアクセスできません。

      パラメータ:
      targetClass - アクセス・チェックされるクラス
      戻り値:
      アクセス・チェックされたクラス
      例外:
      IllegalAccessException - ルックアップ・クラスおよび前のルックアップ・クラスが存在する場合、許可されたアクセス・モードを使用してこのクラスにアクセスできない場合。
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      導入されたバージョン:
      9
      関連項目:
      モジュール間参照
    • findSpecial

      public MethodHandle findSpecial​(Class<?> refc, String name, MethodType type, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException
      仮想メソッドの早期にバインドされるメソッド・ハンドルを生成します。 明示的に指定されたspecialCaller内のinvokespecial命令から呼び出されたかのように、レシーバでのメソッドのオーバーライド・チェックをバイパスします。 メソッド・ハンドルの型はメソッドのもので、適切に制限されたレシーバ型が追加されます。 (レシーバ型はspecialCallerまたはサブタイプです。) このメソッドとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。

      メソッド解決の前に、明示的に指定された呼出し元クラスがルックアップ・クラスと同一でない場合、またはこのルックアップ・オブジェクトがprivateアクセス特権を持たない場合は、アクセスが失敗します。

      返されるメソッド・ハンドルの引数が可変引数になるのは、メソッドの可変引数修飾子ビット(0x0080)が設定されている場合だけです。

      (ノート: "<init>"というJVM内部メソッドは、特殊な環境ではinvokespecial命令はそれらを参照できますが、このAPIでは可視ではありません。 安全な方法でインスタンス初期化メソッドにアクセスするには、findConstructorを使用してください。)

      例:

      
      import static java.lang.invoke.MethodHandles.*;
      import static java.lang.invoke.MethodType.*;
      ...
      static class Listie extends ArrayList {
        public String toString() { return "[wee Listie]"; }
        static Lookup lookup() { return MethodHandles.lookup(); }
      }
      ...
      // no access to constructor via invokeSpecial:
      MethodHandle MH_newListie = Listie.lookup()
        .findConstructor(Listie.class, methodType(void.class));
      Listie l = (Listie) MH_newListie.invokeExact();
      try { assertEquals("impossible", Listie.lookup().findSpecial(
              Listie.class, "<init>", methodType(void.class), Listie.class));
       } catch (NoSuchMethodException ex) { } // OK
      // access to super and self methods via invokeSpecial:
      MethodHandle MH_super = Listie.lookup().findSpecial(
        ArrayList.class, "toString" , methodType(String.class), Listie.class);
      MethodHandle MH_this = Listie.lookup().findSpecial(
        Listie.class, "toString" , methodType(String.class), Listie.class);
      MethodHandle MH_duper = Listie.lookup().findSpecial(
        Object.class, "toString" , methodType(String.class), Listie.class);
      assertEquals("[]", (String) MH_super.invokeExact(l));
      assertEquals(""+l, (String) MH_this.invokeExact(l));
      assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method
      try { assertEquals("inaccessible", Listie.lookup().findSpecial(
              String.class, "toString", methodType(String.class), Listie.class));
       } catch (IllegalAccessException ex) { } // OK
      Listie subl = new Listie() { public String toString() { return "[subclass]"; } };
      assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
       

      パラメータ:
      refc - メソッドのアクセス元となるクラスまたはインタフェース
      name - メソッドの名前(「<init>」であってはいけない)
      type - メソッドの型(レシーバ引数は含まない)
      specialCaller - invokespecialを実行する、提案された呼出し元クラス
      戻り値:
      目的のメソッド・ハンドル
      例外:
      NoSuchMethodException - メソッドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドがstatic,の場合、あるいはメソッドの可変引数修飾子ビットが設定されてasVarargsCollectorが失敗した場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
    • findGetter

      public MethodHandle findGetter​(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
      非staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。 メソッド・ハンドルの型に含まれる戻り値の型は、フィールドの値の型になります。 メソッド・ハンドルの単一の引数は、フィールドを含むインスタンスです。 ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。
      パラメータ:
      refc - メソッドのアクセス元となるクラスまたはインタフェース
      name - フィールドの名前
      type - フィールドの型
      戻り値:
      フィールドから値をロードできるメソッド・ハンドル
      例外:
      NoSuchFieldException - フィールドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはフィールドがstaticの場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
      関連項目:
      findVarHandle(Class, String, Class)
    • findSetter

      public MethodHandle findSetter​(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
      非staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。 このメソッド・ハンドルの型に含まれる戻り値の型は、voidになります。 メソッド・ハンドルが取る2つの引数は、フィールドを含むインスタンスと、格納する値です。 2番目の引数の型は、フィールドの値の型になります。 ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。
      パラメータ:
      refc - メソッドのアクセス元となるクラスまたはインタフェース
      name - フィールドの名前
      type - フィールドの型
      戻り値:
      フィールドに値を格納できるメソッド・ハンドル
      例外:
      NoSuchFieldException - フィールドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはフィールドがstaticまたはfinalである場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
      関連項目:
      findVarHandle(Class, String, Class)
    • findVarHandle

      public VarHandle findVarHandle​(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
      recvのクラスで宣言された型typeの非静的フィールドnameへのアクセスを提供するVarHandleを生成します。 VarHandle変数型はtypeであり、1つの座標型、recvを持ちます。

      ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。

      返されたVarHandleの特定のアクセス・モードは、次の条件ではサポートされません:

      • フィールドがfinalと宣言されている場合、書き込み、アトミック更新、数値アトミック更新、ビット単位アトミック更新アクセス・モードはサポートされません。
      • フィールド型がbyteshortcharintlongfloat、またはdouble以外の場合、数値アトミック更新アクセス・モードはサポートされていません。
      • フィールド型がbooleanbyteshortcharintまたはlong以外の場合、ビット単位アトミック更新アクセス・モードはサポートされていません。

      フィールドがvolatileと宣言されている場合、返されたVarHandleは、指定されたアクセス・モードに従ってフィールド(volatile宣言を効果的に無視)へのアクセスをオーバーライドします。

      フィールド型がfloatまたはdoubleの場合、数値およびアトミック更新アクセス・モードはビット単位の表現(それぞれFloat.floatToRawIntBits(float)Double.doubleToRawLongBits(double)を参照してください)を使用して値を比較します。

      APIのノート:
      数値およびアトミック更新アクセス・モードで実行されるfloat値またはdouble値のビット単位の比較は、基本的な==演算子およびFloat.equals(java.lang.Object)およびDouble.equals(java.lang.Object)メソッドとは異なります(NaN値の比較または-0.0+0.0の比較を参照)。 操作が予期せず失敗する可能性があるため、このような値との比較および設定、比較および交換操作を実行するときは注意が必要です。 JavaではNaNと見なされるNaN値は数多くありますが、Javaが提供するIEEE 754浮動小数点演算では区別できません。 予想される値または目撃者の値がNaN値であり、(おそらくプラットフォーム固有の方法で)が別のNaN値に変換され、したがって異なるビット単位の表現(詳細はFloat.intBitsToFloat(int)またはDouble.longBitsToDouble(long)を参照してください)を持つ場合、操作の失敗が発生する可能性があります。 -0.0+0.0の値は、ビット単位の表現が異なりますが、プリミティブ==演算子を使用する場合、等しいとみなされます。 たとえば、数値アルゴリズムが期待値を-0.0と計算し、前もって+0.0と呼ばれる証人値を計算した場合、演算エラーが発生する可能性があります。
      パラメータ:
      recv - 非静的フィールドを宣言するR型の受信側クラス
      name - フィールドの名前
      type - 型Tのフィールド型
      戻り値:
      非静的フィールドへのアクセスを提供するVarHandle。
      例外:
      NoSuchFieldException - フィールドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはフィールドがstaticの場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
      導入されたバージョン:
      9
    • findStaticGetter

      public MethodHandle findStaticGetter​(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
      staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。 メソッド・ハンドルの型に含まれる戻り値の型は、フィールドの値の型になります。 メソッド・ハンドルは引数を一切取りません。 ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。

      返されるメソッド・ハンドルが呼び出された場合、そのフィールドのクラスは初期化されます(まだ初期化されていない場合)。

      パラメータ:
      refc - メソッドのアクセス元となるクラスまたはインタフェース
      name - フィールドの名前
      type - フィールドの型
      戻り値:
      フィールドから値をロードできるメソッド・ハンドル
      例外:
      NoSuchFieldException - フィールドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはフィールドがstaticでない場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
    • findStaticSetter

      public MethodHandle findStaticSetter​(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
      staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。 このメソッド・ハンドルの型に含まれる戻り値の型は、voidになります。 メソッド・ハンドルは、フィールドの値の型を持つ単一の引数(格納する値)を取ります。 ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。

      返されるメソッド・ハンドルが呼び出された場合、そのフィールドのクラスは初期化されます(まだ初期化されていない場合)。

      パラメータ:
      refc - メソッドのアクセス元となるクラスまたはインタフェース
      name - フィールドの名前
      type - フィールドの型
      戻り値:
      フィールドに値を格納できるメソッド・ハンドル
      例外:
      NoSuchFieldException - フィールドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはフィールドがstaticでないかfinalである場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
    • findStaticVarHandle

      public VarHandle findStaticVarHandle​(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
      declのクラスで宣言された型typeの静的フィールドnameへのアクセスを提供するVarHandleを生成します。 変数VarHandleはtypeであり、座標型はありません。

      ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。

      返されたVarHandleがonに操作された場合、宣言クラスはまだ初期化されていなければ初期化されます。

      返されたVarHandleの特定のアクセス・モードは、次の条件ではサポートされません:

      • フィールドがfinalと宣言されている場合、書き込み、アトミック更新、数値アトミック更新、ビット単位アトミック更新アクセス・モードはサポートされません。
      • フィールド型がbyteshortcharintlongfloat、またはdouble以外の場合、数値アトミック更新アクセス・モードはサポートされていません。
      • フィールド型がbooleanbyteshortcharintまたはlong以外の場合、ビット単位アトミック更新アクセス・モードはサポートされていません。

      フィールドがvolatileと宣言されている場合、返されたVarHandleは、指定されたアクセス・モードに従ってフィールド(volatile宣言を効果的に無視)へのアクセスをオーバーライドします。

      フィールド型がfloatまたはdoubleの場合、数値およびアトミック更新アクセス・モードはビット単位の表現(それぞれFloat.floatToRawIntBits(float)Double.doubleToRawLongBits(double)を参照してください)を使用して値を比較します。

      APIのノート:
      数値およびアトミック更新アクセス・モードで実行されるfloat値またはdouble値のビット単位の比較は、基本的な==演算子およびFloat.equals(java.lang.Object)およびDouble.equals(java.lang.Object)メソッドとは異なります(NaN値の比較または-0.0+0.0の比較を参照)。 操作が予期せず失敗する可能性があるため、このような値との比較および設定、比較および交換操作を実行するときは注意が必要です。 JavaではNaNと見なされるNaN値は数多くありますが、Javaが提供するIEEE 754浮動小数点演算では区別できません。 予想される値または目撃者の値がNaN値であり、(おそらくプラットフォーム固有の方法で)が別のNaN値に変換され、したがって異なるビット単位の表現(詳細はFloat.intBitsToFloat(int)またはDouble.longBitsToDouble(long)を参照してください)を持つ場合、操作の失敗が発生する可能性があります。 -0.0+0.0の値は、ビット単位の表現が異なりますが、プリミティブ==演算子を使用する場合、等しいとみなされます。 たとえば、数値アルゴリズムが期待値を-0.0と計算し、前もって+0.0と呼ばれる証人値を計算した場合、演算エラーが発生する可能性があります。
      パラメータ:
      decl - 静的フィールドを宣言するクラス
      name - フィールドの名前
      type - 型Tのフィールド型
      戻り値:
      静的フィールドにアクセスできるVarHandle
      例外:
      NoSuchFieldException - フィールドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはフィールドがstaticでない場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
      導入されたバージョン:
      9
    • bind

      public MethodHandle bind​(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
      非staticメソッドの早期バインド・メソッド・ハンドルを生成します。 レシーバのスーパー・タイプdefc内では、指定された名前と型を持つメソッドにルックアップ・クラスからアクセスできる必要があります。 このメソッドとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。 メソッド・ハンドルの型はメソッドの型であり、追加のレシーバ・パラメータは一切挿入されません。 指定されたレシーバがメソッド・ハンドルにバインドされるため、メソッド・ハンドルが呼び出されるたびに要求されたメソッドが指定されたレシーバ上で呼び出されるようになります。

      返されるメソッド・ハンドルの引数が可変引数になるのは、メソッドの可変引数修飾子ビット(0x0080)が設定されており、かつ、末尾の配列引数が唯一の引数でない場合だけです。 (末尾の配列引数が唯一の引数である場合、指定されたレシーバの値はその引数にバインドされます。)

      これは、次のコードとほぼ同じですが、いくつかの違いがあります:

      
      import static java.lang.invoke.MethodHandles.*;
      import static java.lang.invoke.MethodType.*;
      ...
      MethodHandle mh0 = lookup().findVirtual(defc, name, type);
      MethodHandle mh1 = mh0.bindTo(receiver);
      mh1 = mh1.withVarargs(mh0.isVarargsCollector());
      return mh1;
       
      ここで、defcreceiver.getClass()またはそのクラスのスーパー・タイプのいずれかであり、その中では、要求されたメソッドにルックアップ・クラスからアクセスできます。 (bindとは異なり、bindToは可変アリティを保持しません。 また、bindToは、メンバーがprotectedであり、レシーバがfindVirtualによってルックアップ・クラスに制限されている場合のように、bindIllegalAccessExceptionをスローするインスタンスでClassCastExceptionをスローすることがあります。

      パラメータ:
      receiver - メソッドのアクセス元となるオブジェクト
      name - メソッドの名前
      type - メソッドの型(レシーバ引数は含まない)
      戻り値:
      目的のメソッド・ハンドル
      例外:
      NoSuchMethodException - メソッドが存在しない場合
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドの可変引数修飾子ビットが設定されていてasVarargsCollectorが失敗した場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
      関連項目:
      MethodHandle.bindTo(java.lang.Object)findVirtual(java.lang.Class<?>, java.lang.String, java.lang.invoke.MethodType)
    • unreflect

      public MethodHandle unreflect​(Method m) throws IllegalAccessException
      ルックアップ・クラスがアクセス権を持つ場合に、mへの直接メソッド・ハンドルを作成します。 mがstaticでない場合、レシーバ引数が最初の引数とみなされます。 mがvirtualの場合、すべての呼出しでオーバーライドが尊重されます。 Core Reflection APIと異なり、例外はラップされません メソッド・ハンドルの型は、メソッドの型の先頭にレシーバの型を追加したものになります(ただし、メソッドがstaticでない場合のみ)。 メソッドのaccessibleフラグが設定されていない場合、ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。 mがpublicでない場合、結果となるハンドルを信頼できない相手と共有しないでください。

      返されるメソッド・ハンドルの引数が可変引数になるのは、メソッドの可変引数修飾子ビット(0x0080)が設定されている場合だけです。

      mがstaticで、返されるメソッド・ハンドルが呼び出された場合、そのメソッドのクラスは初期化されます(まだ初期化されていない場合)。

      パラメータ:
      m - リフレクトされたメソッド
      戻り値:
      リフレクトされたメソッドを呼び出すことができるメソッド・ハンドル
      例外:
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドの可変引数修飾子ビットが設定されていてasVarargsCollectorが失敗した場合
      NullPointerException - 引数がnullの場合
    • unreflectSpecial

      public MethodHandle unreflectSpecial​(Method m, Class<?> specialCaller) throws IllegalAccessException
      リフレクトされたメソッドのメソッド・ハンドルを生成します。 明示的に指定されたspecialCaller内のinvokespecial命令から呼び出されたかのように、レシーバでのメソッドのオーバーライド・チェックをバイパスします。 メソッド・ハンドルの型はメソッドのもので、適切に制限されたレシーバ型が追加されます。 (レシーバ型はspecialCallerまたはサブタイプです。) メソッドのaccessibleフラグが設定されていない場合、invokespecial命令がリンクされていたかのように、ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。

      メソッド解決の前に、明示的に指定された呼出し元クラスがルックアップ・クラスと同一でない場合、またはこのルックアップ・オブジェクトがprivateアクセス特権を持たない場合は、アクセスが失敗します。

      返されるメソッド・ハンドルの引数が可変引数になるのは、メソッドの可変引数修飾子ビット(0x0080)が設定されている場合だけです。

      パラメータ:
      m - リフレクトされたメソッド
      specialCaller - メソッドを形式上呼び出すクラス
      戻り値:
      リフレクトされたメソッドを呼び出すことができるメソッド・ハンドル
      例外:
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドがstatic,の場合、あるいはメソッドの可変引数修飾子ビットが設定されてasVarargsCollectorが失敗した場合
      NullPointerException - いずれかの引数がnullの場合
    • unreflectConstructor

      public MethodHandle unreflectConstructor​(Constructor<?> c) throws IllegalAccessException
      リフレクトされたコンストラクタのメソッド・ハンドルを生成します。 メソッド・ハンドルの型は、コンストラクタの型で、戻り値の型を宣言元クラスに変更したものになります。 メソッド・ハンドルはnewInstance操作を実行し、メソッド・ハンドルに渡された引数に基づいてコンストラクタのクラスの新しいインスタンスを作成します。

      コンストラクタのaccessibleフラグが設定されていない場合、ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。

      返されるメソッド・ハンドルの引数が可変引数になるのは、コンストラクタの可変引数修飾子ビット(0x0080)が設定されている場合だけです。

      返されるメソッド・ハンドルが呼び出された場合、そのコンストラクタのクラスは初期化されます(まだ初期化されていない場合)。

      パラメータ:
      c - リフレクトされたコンストラクタ
      戻り値:
      リフレクトされたコンストラクタを呼び出すことができるメソッド・ハンドル
      例外:
      IllegalAccessException - アクセス・チェックが失敗した場合、またはメソッドの可変引数修飾子ビットが設定されていてasVarargsCollectorが失敗した場合
      NullPointerException - 引数がnullの場合
    • unreflectGetter

      public MethodHandle unreflectGetter​(Field f) throws IllegalAccessException
      リフレクトされたフィールドに対する読取りアクセス権を提供するメソッド・ハンドルを生成します。 メソッド・ハンドルの型に含まれる戻り値の型は、フィールドの値の型になります。 フィールドがstaticの場合、メソッド・ハンドルには引数は必要ありません。 それ以外の場合、その単一の引数は、フィールドを含むインスタンスになります。 Fieldオブジェクトのaccessibleフラグが設定されていない場合は、ルックアップ・クラスのかわりにアクセス・チェックが即時に実行されます。

      フィールドがstaticで、返されるメソッド・ハンドルが呼び出された場合、そのフィールドのクラスは初期化されます(まだ初期化されていない場合)。

      パラメータ:
      f - リフレクトされたフィールド
      戻り値:
      リフレクトされたフィールドから値をロードできるメソッド・ハンドル
      例外:
      IllegalAccessException - アクセス・チェックが失敗した場合
      NullPointerException - 引数がnullの場合
    • unreflectSetter

      public MethodHandle unreflectSetter​(Field f) throws IllegalAccessException
      リフレクトされたフィールドに対する書込みアクセス権を提供するメソッド・ハンドルを生成します。 このメソッド・ハンドルの型に含まれる戻り値の型は、voidになります。 フィールドがstaticの場合、メソッド・ハンドルは、フィールド値の型の単一の引数(格納される値)を取ります。 それ以外の場合、2つの引数は、フィールドを含むインスタンスと格納する値になります。 Fieldオブジェクトのaccessibleフラグが設定されていない場合は、ルックアップ・クラスのかわりにアクセス・チェックが即時に実行されます。

      フィールドがfinalの場合、Field.setについてドキュメント化されている特定の狭い状況を除き、書込みアクセスは許可されず、アクセス・チェックが失敗します。 メソッド・ハンドルが返されるのは、Fieldオブジェクトのsetメソッドへの対応するコールが正常に返された場合のみです。 具体的には、staticfinalの両方であるフィールドを設定しない場合があります。

      フィールドがstaticで、返されたメソッド・ハンドルが呼び出された場合、フィールド・クラスは、初期化されていなければ初期化されます。

      パラメータ:
      f - リフレクトされたフィールド
      戻り値:
      リフレクトされたフィールドに値を格納できるメソッド・ハンドル
      例外:
      IllegalAccessException - アクセス・チェックに失敗した場合、またはフィールドがfinalであり、Fieldオブジェクトで書込みアクセスが有効になっていない場合
      NullPointerException - 引数がnullの場合
    • unreflectVarHandle

      public VarHandle unreflectVarHandle​(Field f) throws IllegalAccessException
      クラスRで宣言されたT型の反映されたフィールドfへのアクセスを提供するVarHandleを生成します。 変数VarHandleはTです。 フィールドが静的でない場合、VarHandleには1つの座標型、Rがあります。 それ以外の場合、フィールドは静的であり、VarHandleには座標型がありません。

      フィールド・チェックaccessibleフラグの値にかかわらず、アクセス・チェックはルックアップ・クラスのために直ちに実行されます。

      フィールドが静的で、返されたVarHandleが操作されている場合、フィールド宣言クラスはまだ初期化されていない場合は初期化されます。

      返されたVarHandleの特定のアクセス・モードは、次の条件ではサポートされません:

      • フィールドがfinalと宣言されている場合、書き込み、アトミック更新、数値アトミック更新、ビット単位アトミック更新アクセス・モードはサポートされません。
      • フィールド型がbyteshortcharintlongfloat、またはdouble以外の場合、数値アトミック更新アクセス・モードはサポートされていません。
      • フィールド型がbooleanbyteshortcharintまたはlong以外の場合、ビット単位アトミック更新アクセス・モードはサポートされていません。

      フィールドがvolatileと宣言されている場合、返されたVarHandleは、指定されたアクセス・モードに従ってフィールド(volatile宣言を効果的に無視)へのアクセスをオーバーライドします。

      フィールド型がfloatまたはdoubleの場合、数値およびアトミック更新アクセス・モードはビット単位の表現(それぞれFloat.floatToRawIntBits(float)Double.doubleToRawLongBits(double)を参照してください)を使用して値を比較します。

      APIのノート:
      数値およびアトミック更新アクセス・モードで実行されるfloat値またはdouble値のビット単位の比較は、基本的な==演算子およびFloat.equals(java.lang.Object)およびDouble.equals(java.lang.Object)メソッドとは異なります(NaN値の比較または-0.0+0.0の比較を参照)。 操作が予期せず失敗する可能性があるため、このような値との比較および設定、比較および交換操作を実行するときは注意が必要です。 JavaではNaNと見なされるNaN値は数多くありますが、Javaが提供するIEEE 754浮動小数点演算では区別できません。 予想される値または目撃者の値がNaN値であり、(おそらくプラットフォーム固有の方法で)が別のNaN値に変換され、したがって異なるビット単位の表現(詳細はFloat.intBitsToFloat(int)またはDouble.longBitsToDouble(long)を参照してください)を持つ場合、操作の失敗が発生する可能性があります。 -0.0+0.0の値は、ビット単位の表現が異なりますが、プリミティブ==演算子を使用する場合、等しいとみなされます。 たとえば、数値アルゴリズムが期待値を-0.0と計算し、前もって+0.0と呼ばれる証人値を計算した場合、演算エラーが発生する可能性があります。
      パラメータ:
      f - T型のフィールドとR型の宣言型クラスを持つ反映されたフィールド
      戻り値:
      非静的フィールドまたは静的フィールドにアクセスするためのVarHandle
      例外:
      IllegalAccessException - アクセス・チェックが失敗した場合
      NullPointerException - 引数がnullの場合
      導入されたバージョン:
      9
    • revealDirect

      public MethodHandleInfo revealDirect​(MethodHandle target)
      この参照オブジェクトまたは類似のオブジェクトによって作成された直接メソッド・ハンドルを解読します。 このルックアップ・オブジェクトがターゲット・メソッド・ハンドルを再作成できるように、セキュリティおよびアクセス・チェックが実行されます。 これは、ターゲットが直接メソッド・ハンドルであるけれども、関連しないルックアップ・オブジェクトによって作成された場合は、解決が失敗する可能性があることを意味します。 これは、メソッド・ハンドルが呼出し元依存で、異なるクラスのルックアップ・オブジェクトによって作成された場合に発生する可能性があります。
      パラメータ:
      target - シンボリック参照コンポーネントに解決する直接メソッド・ハンドル
      戻り値:
      このルックアップ・オブジェクトからこのメソッド・ハンドルを再構築するために使用できるシンボリック参照
      例外:
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      IllegalArgumentException - ターゲットが直接メソッド・ハンドルでない場合、またはアクセス・チェックが失敗した場合
      NullPointerException - ターゲットがnullの場合
      導入されたバージョン:
      1.8
      関連項目:
      MethodHandleInfo
    • hasPrivateAccess

      @Deprecated(since="14") public boolean hasPrivateAccess()
      Deprecated.
      このメソッドは、当初は、完全な権限アクセスを意味するPRIVATEアクセスをテストするように設計されましたが、MODULEアクセスはPRIVATEアクセスから独立しているためです。 hasFullPrivilegeAccess()を呼び出すことをお薦めします。
      この参照にPRIVATEおよびMODULEアクセス権がある場合はtrueを返します。
      戻り値:
      この参照にPRIVATEおよびMODULEアクセス権がある場合、true
      導入されたバージョン:
      9
    • hasFullPrivilegeAccess

      public boolean hasFullPrivilegeAccess()
      この参照にPRIVATEおよびMODULEアクセス権などの「完全な権限アクセス」がある場合、trueを返します。 「ルックアップ・クラス」にアクセス可能なすべてのメンバーにアクセスするには、Lookupオブジェクトへの完全なアクセス権限が必要です。
      戻り値:
      この参照に完全な権限アクセスがある場合、true
      導入されたバージョン:
      14
      関連項目:
      プライベートおよびモジュール・アクセス