- 含まれているクラス:
- MethodHandles
メソッド・ハンドルを作成する必要のあるルックアップ・クラスは、MethodHandles.lookup
を呼び出して自分用のファクトリを作成します。 Lookup
ファクトリ・オブジェクトの作成時には、ルックアップ・クラスのアイデンティティが決定され、その情報がLookup
オブジェクト内にセキュアに格納されます。 その後、ルックアップ・クラス(またはその委譲先)は、Lookup
オブジェクトのファクトリ・メソッドを使ってアクセス・チェックされたメンバーのメソッド・ハンドルを作成できます。 これには、ルックアップ・クラスに許可されるメソッド、コンストラクタ、およびフィールドがすべて含まれます(privateのものも含む)。
Lookupファクトリ・メソッド
Lookup
オブジェクトのファクトリ・メソッドは、メソッド、コンストラクタ、およびフィールドのすべてのメジャーなユース・ケースに対応しています。 ファクトリ・メソッドによって作成される各メソッド・ハンドルは、特定のバイトコード動作と機能的に同等です。 (バイトコードの動作は、Java Virtual Machine仕様の5.4.3.5の項で説明されています。) これらのファクトリ・メソッドと、結果として得られるメソッド・ハンドルの動作との対応のサマリーを以下に示します:
ルックアップ式 | member | バイトコード動作 |
---|---|---|
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
という名前のパラメータとしてドキュメント化されています。 仮パラメータthis
はC
型の自己参照を表しています。これは、存在する場合は常にメソッド・ハンドル呼出しの先頭の引数になります。 (一部のprotected
メンバーでは、this
の型がルックアップ・クラスに制限される場合があります。下記を参照してください。) 名前arg
は、メソッド・ハンドルのほかのすべての引数を表しています。 Core Reflection APIのコード例に含まれる名前thisOrNull
は、アクセス対象のメソッドやフィールドがstaticの場合はnull参照を表し、それ以外の場合はthis
を表します。 aMethod
、aField
およびaConstructor
の名前は、C
に宣言された特定のメンバーに対応するリフレクト・オブジェクトを表します。
findClass
操作のバイトコード動作は、ldc CONSTANT_Class
の場合と同様に、定数クラスのロードです。 振る舞いは、メソッド・ハンドルとしてではなく、直接Class
定数として表されます。
指定されたメンバーが可変引数(つまりメソッドまたはコンストラクタ)の場合、返されるメソッド・ハンドルも可変引数になります。 その他のすべての場合、返されるメソッド・ハンドルは固定引数になります。
ディスカッション: ルックアップされたメソッド・ハンドルと基礎となるクラス・メンバーとバイトコード動作との間の等価性が、いくつかの方法で壊れることがあります。
C
がルックアップ・クラスのローダーからシンボルでアクセスできない場合でも、ルックアップが成功することがあります(同等のJava式やバイト・コード定数が存在しない場合でも)。- 同様に、
T
またはMT
がルックアップ・クラスのローダーからシンボルでアクセスできない場合でも、ルックアップが成功することがあります。 たとえば、MethodHandle.invokeExact
やMethodHandle.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仕様の4.9.2、5.4.3.5および6.4の項を参照してください。) また、目的のメンバーが別のパッケージ内にある非staticフィールドまたはメソッドである場合、結果となるメソッド・ハンドルはルックアップ・クラスまたはそのいずれかのサブクラスのオブジェクトにしか適用されない可能性があります。 この要件は、先頭のthis
パラメータの型をC
(必ずルックアップ・クラスのスーパー・クラスになる)からルックアップ・クラス自体にナロー変換することで強制されます。
JVMは同様の要件をinvokespecial
命令に適用します(レシーバ引数が解決済メソッドおよび現在のクラスに一致する必要がある)。 さらにこの要件は、先頭パラメータの型を結果のメソッド・ハンドルにナロー変換することで適用されます。 (Java Virtual Machine仕様の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
はほかの関連クラス(C
、C.D.E
、C.B
など)の内部のprivateメンバーにアクセスできますが、Javaコンパイラがそれらの関連クラス内でラッパー・メソッドを生成しなければいけない可能性があります。 このような場合、C.E
上のLookup
オブジェクトはそのプライベート・メンバーにアクセスできません。 この制限の回避方法の1つがLookup.in
メソッドであり、これを使うことで、特権レベルを特別に上げることなくC.E
のルックアップをそうしたほかのクラスのいずれかのルックアップに変換できます。
指定されたルックアップ・オフセットに許可されるアクセスは、そのlookupModes
セットに基づいて、ルックアップ・クラスから通常アクセスできるメンバー・サブセットに制限される場合があります。 たとえば、publicLookup
メソッドは、エクスポートされたパッケージのパブリック・クラスのパブリック・メンバーにのみアクセスできるルックアップ・オブジェクトを生成します。 呼出し元依存メソッドlookup
は、サポートされているすべてのバイトコード動作をエミュレートする、呼出し元クラスに関連するあらゆる機能を持つルックアップ・オブジェクトを生成します。 また、Lookup.in
メソッドは元のルックアップ・オブジェクトよりアクセス・モードが少ないルックアップ・オブジェクトを生成できます。
プライベート・アクセスとモジュール・アクセスについての説明:そのルックアップ・モードがprivate
メンバー(ネストのプライベート・メンバーを含む)へのアクセスの可能性が含まれていると、参照にはプライベート・アクセスがあると呼びます。 ドキュメント内の関連メソッドに記述されているように、privateアクセスを持つルックアップのみが次の機能を持ちます。
- ルックアップ・クラスおよびそのネスト元のプライベート・フィールド、メソッドおよびコンストラクタへのアクセス
invokespecial命令をエミュレートする
メソッド・ハンドルを作成する- ルックアップ・クラスからアクセスできるクラスに対するパッケージ・アクセス・チェックを回避する
- 同じパッケージ・メンバー内の他のクラスに対するprivateアクセスを持つ、
委譲されたルックアップ・オブジェクト
を作成する
同様に、モジュール・アクセスを持つ参照では、元の参照作成者が参照クラスと同じモジュール内のメンバーであることが保証されます。
プライベートおよびモジュールへのアクセスは、独立して決定されるモードであり、参照には両方、またはどちらもない可能性があります。 両方のアクセス・モードを持つ参照は、「完全な権限アクセス」と言われます。
「元のアクセス」を使用したルックアップでは、このルックアップが元のルックアップ・クラスによって作成され、ブートストラップ・メソッドがVMによって呼び出されることが保証されます。 元のアクセス権を持つこのようなルックアップには、次の追加機能を持つプライベートおよびモジュール・アクセス権もあります:
これらのことが許可されるのは、privateアクセスを持つルックアップ・オブジェクトから元のクラスまで安全にたどることができ、そのバイトコード動作およびJava言語アクセス権をメソッド・ハンドルが確実に判断してエミュレートできるという事実の結果です。
モジュール間参照
あるモジュールM1
の参照クラスが別のモジュールM2
にあるクラスにアクセスする場合、アクセス・モード・ビットの範囲を超えて余分なアクセス・チェックが実行されます。 PUBLIC
モードのLookup
およびM1
の参照クラスでは、M2
がM1
に対して読取り可能である場合、およびタイプがM1
以上にエクスポートされるM2
のパッケージ内にある場合、M2
のパブリック・タイプにアクセスできます。
C
上のLookup
では、Lookup.in
およびMethodHandles.privateLookupIn
メソッドを介してターゲット・クラスに「テレ・ポート」を実行することもできます。 モジュール間でのポートレット化では、「前のルックアップ・クラス」として元の参照クラスが常に記録され、MODULE
アクセス権が削除されます。 ターゲット・クラスがルックアップ・クラスC
と同じモジュール内にある場合、そのターゲット・クラスは新しいルックアップ・クラスになり、以前のルックアップ・クラスに変更はありません。 ターゲット・クラスがM1
(C
のモジュール)とは異なるモジュールにある場合は、C
が新しい以前の参照クラスになり、ターゲット・クラスが新しい参照クラスになります。 その場合、M0
に以前のルックアップ・クラスがすでに存在し、M1
とM2
と異なる場合は、結果のルックアップがすべての権限をドロップします。 次に例を示します。
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)
は、クラスC
のlookup
を、権限を昇格させずにD
クラスに変換します。 C
とD
が同じモジュールの場合、lookup2
はD
を新しい参照クラスとして記録し、元のlookup
と同じ前の参照クラスを維持します。存在しない場合は、null
になります。
あるネストされたクラスから別のネストされたクラスへのLookup
テレ・ポートを実行すると、PRIVATE
アクセス権が削除されます。 あるパッケージのクラスから別のパッケージへのLookup
テレ・ポートを実行すると、PACKAGE
にアクセスできなくなります。 あるモジュールのクラスから別のモジュールへのLookup
ポートが提供されると、MODULE
アクセス権が切断されます。 モジュール間のテレティングでは、新しいルックアップ・クラスのモジュールと古いルックアップ・クラスのモジュールの両方から、エクスポートされていないクラスにアクセスする機能をドロップします。そうすると、Lookup
ではPUBLIC
アクセスのみが可能になります。 Lookup
は、参照クラスのモジュール内のクラスおよび前のクラス参照のモジュールに電話をかけて移動できます。 モジュール間の通信は、アクセス権を減らすことのみができますが、増やすことはできません。 3つ目のモジュールに通信している場合は、すべてのアクセスを削除します。
前述の例では、C
とD
が異なるモジュールにある場合、lookup2
はD
をその参照クラスとして記録し、lookup2
にはPUBLIC
アクセスのみがあります。lookup2
は、C
'モジュールおよびD
'モジュールの他のクラスへの通信を行えます。 E
クラスが3番目のモジュールにある場合、lookup2.in(E.class)
はアクセスなしでE
にLookup
を作成し、lookup2
の参照クラスD
は以前の参照クラスとして記録されます。
モジュール間の通信によって、参照クラスと前の参照クラスの両方が(下記参照)に同等にアクセスできるパブリック・タイプにアクセスが制限されます。
参照クラスがT
で「深い反射」を実行できる場合、MethodHandles.privateLookupIn(T.class, lookup)
を使用して、C
クラスからT
クラスへのlookup
の通信を行い、「プライベート・アクセス」との新しいLookup
を作成できます。 lookup
でprivateLookupIn
をコールするには、MODULE
およびPRIVATE
アクセス権が必要です。 モジュールM1
のC
上でのlookup
は、M1
内のすべてのクラスに対してディープ・リフレクションを実行できます。 T
がM1
に含まれる場合、privateLookupIn
では、完全な機能を備えたT
上に新しいLookup
が生成されます。 C
でのlookup
は、M1
がM2
、M2
opens
にM1
を含むパッケージを読み取る場合に、別のモジュールM2
でT
をさらに深くリフレクションすることもできます。 T
が新しい参照クラスになり、C
が新しい以前の参照クラスになり、MODULE
のアクセス権が結果のLookup
から削除されます。 結果のLookup
を使用すると、Lookup::in
をコールして、別の参照クラスにメンバー参照またはテレ・ポートを実行できます。 ただし、MODULE
アクセス権がないため、privateLookupIn
をコールして別のプライベートLookup
を取得するためには使用できません。
モジュール間アクセス・チェック
PUBLIC
を含むLookup
またはUNCONDITIONAL
モードを使用すると、モジュール間アクセスが可能になります。 アクセス・チェックは、参照クラスと前の参照クラス(存在する場合)の両方に対して実行されます。
UNCONDITIONAL
モードのLookup
では、すべてのモジュールのパブリック・タイプは「無条件でエクスポート」のパッケージの中にアクセスできます。
M1
のLC
のLookup
に以前の参照クラスがない場合、PUBLIC
モードで参照すると、M1
で読取り可能なモジュール内のすべてのパブリック・タイプにアクセスでき、タイプは少なくともM1
にエクスポートされるパッケージ内にあります。
M1
のLC
のLC
に以前の参照クラスM0
の前の参照クラスPLC
がある場合、PUBLIC
モードでの参照は、PUBLIC
モードで参照すると、M0
からアクセス可能なすべてのパブリック・タイプを使用して、M1
でアクセスできるすべてのパブリック・タイプの共通部分にアクセスできます。 M0
はM1
を読み取るため、アクセス可能なタイプのセットには次のものがあります:
M0 およびM1 に均等にアクセス可能な型 |
---|
M1 からの無条件エクスポートのパッケージ |
M1 がM0 を読み込む場合、M0 から無条件エクスポート・パッケージをエクスポート |
M0 とM1 の両方がM2 を読み上げた場合、第3のモジュールM2 から無条件エクスポートのパッケージをエクスポート |
レイヤー化されたエクスポート済パッケージ: M1 からM0 へ |
M1 がM0 を読み取った場合に、M0 からM1 に並列エクスポートされたパッケージ |
M0 とM1 の両方がM2 を読む場合、3番目のモジュールM2 からM0 とM1 の両方にレイヤー化されたエクスポートされたパッケージ |
アクセス・モード
次の表に、ファクトリまたは変換のいずれかのメソッドによって生成されるLookup
のアクセス・モードを示します:
MethodHandles::lookup
MethodHandles::publicLookup
MethodHandles::privateLookupIn
Lookup::in
Lookup::dropLookupMode
オブジェクトの参照 | original | protected | private | package | module | public |
---|---|---|---|---|---|---|
C のCL = MethodHandles.lookup() |
ORI | 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
内にありますが、D
とD2
はモジュールM2
で、E
はモジュールM3
にあります。X
は、参照がアクセス不可能なクラスを探します。ANY
は、サンプル・ルックアップの表します。ORI
はORIGINAL
ビット・セットを示し、PRO
はPROTECTED
ビット・セットを示し、PRI
はPRIVATE
ビット・セットを示し、PAC
はPACKAGE
ビット・セットを示し、MOD
はMODULE
ビット・セットを示し、1R
と2R
はPUBLIC
コード・セットを示し、U
はUNCONDITIONAL
ビット・セットを示し、IAE
はスローされたIllegalAccessException
を示します。- パブリック・アクセスには、次の3種類があります:
- 無条件(
U
): ルックアップは読みやすくなっています。 ルックアップにnull
前のルックアップ・クラスがある場合。 - one-module-reads (
1R
): モジュール・アクセス・チェックは、参照クラスに対して実行します。 ルックアップにnull
前のルックアップ・クラスがある場合。 - two-module-reads (
2R
): モジュール・アクセス・チェックは、参照クラスおよび前の参照クラスについて実行されます。 ルックアップに、現在のルックアップ・クラスとは異なるモジュール内にあるnull以外の前のルックアップ・クラスが含まれています。
- 無条件(
- 3つ目のモジュールに到達しようとすると、すべてのアクセスが失われます。
Lookup::in
では、ターゲット・クラスX
にアクセスできない場合、すべてのアクセス・モードが削除されます。
セキュリティ・マネージャとの対話
バイト・コード命令は関連クラス・ローダー内のクラスしか参照できませんが、このAPIでは、Class
オブジェクトへの参照が使用可能であるかぎり、任意のクラス内のメソッドを検索できます。 そのようなクロスローダー参照は、Core Reflection APIでも可能ですが、invokestatic
やgetfield
などのバイト・コード命令では不可能です。 アプリケーション内でそのようなクロスローダー参照をチェックできるようにするためのセキュリティ・マネージャAPIが存在します。 それらのチェックは、MethodHandles.Lookup
APIと(Class
上に存在する) Core Reflection APIの両方に適用されます。
セキュリティ・マネージャが存在する場合、メンバーおよびクラスのルックアップは追加検査の対象となります。 セキュリティ・マネージャに対して1回から3回の呼出しが行われます。 これらの呼出しのいずれも、SecurityException
をスローすることでアクセスを拒否できます。 smgr
をセキュリティ・マネージャとして、lookc
を現在のルックアップ・オブジェクトのルックアップ・クラスとして、refc
をメンバーを検索する包含クラスとして、defc
をメンバーが実際に定義されるクラスとして定義してください。 (クラスまたは他の型がアクセスされている場合、refc
およびdefc
の値はクラスそのものです。) 現在の参照オブジェクトに「完全な権限アクセス」が含まれない場合、lookc
値は「存在しない」と定義されます。 次のルールに従って呼出しが行われます。
- ステップ1:
lookc
が存在しない場合、またはそのクラス・ローダーがrefc
のクラス・ローダーと同じでもその祖先でもない場合は、smgr.checkPackageAccess(refcPkg)
が呼び出されます(refcPkg
はrefc
のパッケージ)。 - ステップ2a: 取り出されたメンバーが公開されておらず、
lookc
が存在しない場合は、RuntimePermission("accessDeclaredMembers")
を含むsmgr.checkPermission
が呼び出されます。 - ステップ2b: 取得したクラスに
null
クラス・ローダーがあり、lookc
が存在しない場合は、RuntimePermission("getClassLoader")
を含むsmgr.checkPermission
が呼び出されます。 - ステップ3: 取得されるメンバーがpublicでなく、
lookc
が存在せず、defc
とrefc
が異なる場合は、smgr.checkPackageAccess(defcPkg)
が呼び出されます(defcPkg
はdefc
のパッケージ)。
セキュリティ・マネージャが存在し、現在のルックアップ・オブジェクトに「完全な権限アクセス」がない場合、defineClass
、defineHiddenClass
、defineHiddenClassWithClassData
はsmgr.checkPermission
をRuntimePermission("defineClass")
とともにコールします。
呼出し元依存メソッド
少数のJavaメソッドに、呼出し元依存性という特殊なプロパティがあります。 呼出し元依存メソッドは、その直接の呼出し元の識別情報によって異なる動作をする可能性があります。呼出し元依存メソッドのメソッド・ハンドルが要求された場合は、バイトコード動作の一般ルールが適用されますが、ルックアップ・クラスは特別な方法で考慮されます。 結果のメソッド・ハンドルはルックアップ・クラスに含まれている命令から呼び出されたように動作し、呼出し元依存メソッドはルックアップ・クラスを検出します。 (一方、メソッド・ハンドルのインボーカは無視されます。) したがって、呼出し元依存メソッドの場合は、ルックアップ・クラスごとにメソッド・ハンドルの動作が異なる可能性があります。
ルックアップ・オブジェクトがpublicLookup()
の場合や、「元のアクセス」を使用しないその他のルックアップ・オブジェクトの場合は、ルックアップ・クラスが無視されます。 そのような場合、呼出し元依存メソッド・ハンドルを作成できず、アクセスは禁止され、ルックアップはIllegalAccessException
で失敗します。
ディスカッション: たとえば、呼出し元依存メソッドClass.forName(x)
は、それを呼び出すクラスのクラス・ローダーに応じて、返されるクラスを異なったり、スローされる例外が異なったりする可能性があります。 Class.forName
のpublicルックアップは失敗します。そのバイトコード動作を判別するための妥当な方法がないためです。
広範囲な共有のためにメソッド・ハンドルをキャッシュするアプリケーションの場合は、publicLookup()
を使用してメソッド・ハンドルを作成することをお薦めします。 Class.forName
のルックアップがある場合、それは失敗し、アプリケーションはその場合に適切なアクションを取る必要があります。 たとえば、後のルックアップ(おそらくブートストラップ・メソッドの呼び出し中)が呼出し元固有の識別情報を組み込むことで、メソッドをアクセス可能にするアクションです。
関数MethodHandles.lookup
は呼出し元依存なので、ルックアップ用の安全な基盤が存在できます。 JSR 292 API内の他のほとんどすべてのメソッドはルックアップ・オブジェクトに依存してアクセス要求をチェックします。
-
ネストされたクラスのサマリー
修飾子と型クラス説明static class
Lookup::defineHiddenClass
メソッドによって作成された非表示クラスをルックアップ・クラスのネストに新しいメンバーとして動的に追加するかどうか、または非表示クラスがその定義ローダーとしてマークされたクラス・ローダーと強力な関係を持つかどうか(あるいはその両方)を指定するクラス・オプションのセット。 -
フィールドのサマリー
修飾子と型フィールド説明static int
module
のアクセスを表すシングルトン・マスクで、lookupModes
の結果に影響する可能性があります。static int
original
アクセスを表す1ビット・マスクで、lookupModes
の結果に寄与する可能性があります。static int
package
アクセス(デフォルト・アクセス)を表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
private
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
protected
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
public
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
unconditional
アクセスを表す単一ビット・マスクで、lookupModes
の結果に寄与する可能性があります。 -
メソッドのサマリー
修飾子と型メソッド説明Class<?>
accessClass(Class<?> targetClass)
このLookup
オブジェクトによって定義されたルックアップ・コンテキストからクラスにアクセスできるかどうかを判定します。bind(Object receiver, String name, MethodType type)
非staticメソッドの早期バインド・メソッド・ハンドルを生成します。Class<?>
defineClass(byte[] bytes)
ClassLoader::defineClass
をコールする場合と同様に、このルックアップ「ルックアップ・クラス」と同じクラス・ローダー、同じランタイム・パッケージおよび「保護ドメイン」で、bytes
からクラスまたはインタフェースを作成してリンクします。defineHiddenClass(byte[] bytes, boolean initialize, MethodHandles.Lookup.ClassOption... options)
bytes
からhiddenクラスまたはインタフェースを作成し、新しく作成されたクラスまたはインタフェースにLookup
を返します。defineHiddenClassWithClassData(byte[] bytes, Object classData, boolean initialize, MethodHandles.Lookup.ClassOption... options)
関連付けられた「クラス・データ」を使用してbytes
からhiddenクラスまたはインタフェースを作成し、新しく作成されたクラスまたはインタフェースでLookup
を返します。dropLookupMode(int modeToDrop)
このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。Class<?>
ensureInitialized(Class<?> targetClass)
targetClass
が初期化されていることを確認します。Class<?>
このLookup
オブジェクト「解決された場合」によってldc
の命令で定義された参照コンテキストから名前でクラスを検索します。findConstructor(Class<?> refc, MethodType type)
指定された型のコンストラクタを使ってオブジェクトの作成と初期化を行うメソッド・ハンドルを生成します。findGetter(Class<?> refc, String name, Class<?> type)
非staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。findSetter(Class<?> refc, String name, Class<?> type)
非staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。findSpecial(Class<?> refc, String name, MethodType type, Class<?> specialCaller)
仮想メソッドの早期にバインドされるメソッド・ハンドルを生成します。findStatic(Class<?> refc, String name, MethodType type)
staticメソッドのメソッド・ハンドルを生成します。findStaticGetter(Class<?> refc, String name, Class<?> type)
staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。findStaticSetter(Class<?> refc, String name, Class<?> type)
staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。findStaticVarHandle(Class<?> decl, String name, Class<?> type)
型decl
のクラスで宣言された型type
の静的フィールドname
へのアクセスを提供するVarHandleを生成します。findVarHandle(Class<?> recv, String name, Class<?> type)
型recv
のクラスで宣言された型type
の非静的フィールドname
へのアクセスを提供するVarHandleを生成します。findVirtual(Class<?> refc, String name, MethodType type)
仮想メソッドのメソッド・ハンドルを生成します。boolean
この参照に「完全な権限アクセス」がある場合、つまりtrue
を返します。boolean
非推奨。指定された新しいルックアップ・クラスでルックアップを作成します。Class<?>
ルックアップを実行しているクラスを示します。int
このルックアップ・オブジェクトがどのアクセス保護クラスのメンバーを生成できるかを示します。Class<?>
この参照オブジェクトが以前に電話をかけていた別のモジュール、またはnull
で参照区分を報告します。revealDirect(MethodHandle target)
この参照オブジェクトまたは類似のオブジェクトによって作成された直接メソッド・ハンドルを解読します。toString()
ルックアップを行うクラスの名前、"/"および「前のルックアップ・クラス」の名前(存在する場合)が表示されます。ルックアップ・クラスがアクセス権を持つ場合に、mへの直接メソッド・ハンドルを作成します。unreflectConstructor(Constructor<?> c)
リフレクトされたコンストラクタのメソッド・ハンドルを生成します。unreflectGetter(Field f)
リフレクトされたフィールドに対する読取りアクセス権を提供するメソッド・ハンドルを生成します。unreflectSetter(Field f)
リフレクトされたフィールドに対する書込みアクセス権を提供するメソッド・ハンドルを生成します。unreflectSpecial(Method m, Class<?> specialCaller)
リフレクトされたメソッドのメソッド・ハンドルを生成します。クラスR
で宣言されたT
型の反映されたフィールドf
へのアクセスを提供するVarHandleを生成します。
-
フィールド詳細
-
PUBLIC
public static final int PUBLICpublic
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。 値0x01
はたまたま、public
修飾子ビットの値と同じになっています。この参照モードの
Lookup
では、「ルックアップ・クラス」および「前のルックアップ・クラス」(存在する場合)について、モジュール間アクセス・チェックが実行されます。- 関連項目:
- 定数フィールド値
-
PRIVATE
public static final int PRIVATEprivate
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。 値0x02
はたまたま、private
修飾子ビットの値と同じになっています。- 関連項目:
- 定数フィールド値
-
PROTECTED
public static final int PROTECTEDprotected
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。 値0x04
はたまたま、protected
修飾子ビットの値と同じになっています。- 関連項目:
- 定数フィールド値
-
PACKAGE
public static final int PACKAGEpackage
アクセス(デフォルト・アクセス)を表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。 値は0x08
ですが、これは、特定のどの修飾子ビットにも、意味のあるかたちでは対応しません。- 関連項目:
- 定数フィールド値
-
MODULE
public static final int MODULEmodule
のアクセスを表すシングルトン・マスクで、lookupModes
の結果に影響する可能性があります。 値は0x10
です。これは特定の「修飾子ビット」には意味がありません。PUBLIC
修飾子ビットと組み合わせて、このルックアップ・モードを持つLookup
は、ルックアップ・クラスのモジュール内のすべてのパブリック型と、他のモジュールによってルックアップ・クラスのモジュールにエクスポートされたパブリック型にアクセスできます。この参照モードが設定されている場合、「前のルックアップ・クラス」は常に
null
です。- 導入されたバージョン:
- 9
- 関連項目:
- 定数フィールド値
-
UNCONDITIONAL
public static final int UNCONDITIONALunconditional
アクセスを表す単一ビット・マスクで、lookupModes
の結果に寄与する可能性があります。 値は0x20
です。これは特定の「修飾子ビット」には意味がありません。 このルックアップ・モードのLookup
はreadabilityを想定しています。 この参照モードでは、タイプがexported unconditionally
であるパッケージ内にある場合、すべてのモジュールのパブリック・タイプのすべてのパブリック・メンバーにアクセスできます。この参照モードが設定されている場合、「前のルックアップ・クラス」は常に
null
です。- 導入されたバージョン:
- 9
- 関連項目:
MethodHandles.publicLookup()
, 「定数フィールド値」
-
ORIGINAL
public static final int ORIGINALoriginal
アクセスを表す1ビット・マスクで、lookupModes
の結果に寄与する可能性があります。 値は0x40
です。これは特定の「修飾子ビット」には意味がありません。このルックアップ・モードが設定されている場合、
Lookup
オブジェクトは、MethodHandles.lookup()
メソッドをコールするか、VMによって起動されるブートストラップ・メソッドによって、元のルックアップ・クラスによって作成される必要があります。 このルックアップ・モードのLookup
オブジェクトには、「完全な権限アクセス」があります。- 導入されたバージョン:
- 16
- 関連項目:
- 定数フィールド値
-
-
メソッドの詳細
-
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)およびORIGINAL (0x40)のビット・マスクになります。「呼び出し元クラス」の新しく作成された検索オブジェクトには、
UNCONDITIONAL
を除くすべての可能なビットが設定されています。 以前のルックアップ・オブジェクトから作成された新しいルックアップ・クラス上のルックアップ・オブジェクトでは、いくつかのモード・ビットがゼロに設定されている可能性があります。 また、モード・ビットは「直接クリア」できます。 クリアされると、モード・ビットはダウングレードされたルックアップ・オブジェクトからリストアできません。 その目的は、新しいルックアップ・オブジェクト経由でのアクセスを制限し、元のルックアップ・オブジェクトと新しいルックアップ・クラスの両方から到達可能な名前だけにアクセスできるようにすることです。- 戻り値:
- ルックアップ・モード、このルックアップ・オブジェクトによって実行されるアクセスの種類を制限する
- 関連項目:
in(java.lang.Class<?>)
,dropLookupMode(int)
-
in
public MethodHandles.Lookup in(Class<?> requestedLookupClass)指定された新しいルックアップ・クラスでルックアップを作成します。 結果となるオブジェクトは、指定されたクラスを自身のlookupClass
として報告します。ただし、結果となる
Lookup
オブジェクトは、元のオブジェクトと同等以下のアクセス機能しか持たないことが保証されます。 具体的には、アクセス機能が次のように失われる可能性があります。- 新しいルックアップ・クラスが古いルックアップ・クラスと異なる場合、つまり
ORIGINAL
アクセスが失われた場合。 - 新しいルックアップ・クラスが古いクラスとは別のモジュールにある場合、つまり
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)このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。 削除するルックアップ・モードは、PUBLIC
、MODULE
、PACKAGE
、PROTECTED
、PRIVATE
、ORIGINAL
またはUNCONDITIONAL
のいずれかです。このルックアップが「パブリック・ルックアップ」の場合、このルックアップには
UNCONDITIONAL
モードが設定され、他のモードは設定されていません。 パブリック・ルックアップにUNCONDITIONAL
をドロップすると、結果のルックアップにアクセスできなくなります。このルックアップがパブリック・ルックアップでない場合、「ルックアップ・モード」に関係なく次のことが適用されます。
PROTECTED
およびORIGINAL
は常に削除されるため、結果として得られるルックアップ・モードにはこれらのアクセス機能はありません。PACKAGE
を削除すると、結果のルックアップにはPACKAGE
またはPRIVATE
アクセスがありません。MODULE
をドロップすると、結果のルックアップにはMODULE
、PACKAGE
、またはPRIVATE
アクセスがありません。PUBLIC
を削除すると、結果のルックアップにアクセスできなくなります。- APIのノート:
PRIVATE
モードではなくPACKAGE
を参照すると、「プライベート・アクセス」を提供せずに、参照クラスのパッケージ内でパブリックでないアクセスを安全に委任できます。PACKAGE
モードではなくMODULE
を参照すると、パッケージ・アクセス権を付与せずに、参照クラスのモジュール内でPUBLIC
アクセスを安全に委任できます。 「前のルックアップ・クラス」 (およびPUBLIC
。MODULE
モードではありません)を使用した参照では、参照クラスのモジュールと以前の参照クラスのモジュールの両方からアクセス可能なパブリック・クラスに安全にアクセス権を委任できます。- パラメータ:
modeToDrop
- ルックアップ・モードをドロップ- 戻り値:
- 示されたモードを持たない参照オブジェクト、または変更がなければ同じオブジェクト
- 例外:
IllegalArgumentException
-modeToDrop
がPUBLIC
,MODULE
,PACKAGE
,PROTECTED
,PRIVATE
,ORIGINAL
またはUNCONDITIONAL
のいずれでもない場合- 導入されたバージョン:
- 9
- 関連項目:
MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
-
defineClass
public Class<?> defineClass(byte[] bytes) throws IllegalAccessExceptionClassLoader::defineClass
をコールする場合と同様に、このルックアップ「ルックアップ・クラス」と同じクラス・ローダー、同じランタイム・パッケージおよび「保護ドメイン」で、bytes
からクラスまたはインタフェースを作成してリンクします。このルックアップの「ルックアップ・モード」には、
PACKAGE
アクセスが含まれている必要があります。デフォルトでは、(package)メンバーはクラスにアクセスできます。PACKAGE
ルックアップ・モードは、ルックアップ・オブジェクトがランタイム・パッケージ(または適切に特権コードによって作成されたルックアップから、ランタイム・パッケージ内のターゲット・クラスに派生)の呼び出し側によって作成されたことを認証する役割を果たします。bytes
パラメータは、ルックアップ・クラスと同じパッケージ内のクラス名を持つ有効なクラス・ファイル(「Java Virtual Machine仕様」で定義されている)のクラス・バイトです。このメソッドは、クラス初期化子を実行しません。 クラス初期化子は、「Java言語仕様」のセクション12.4で詳しく説明するように、後で実行することができます。
セキュリティ・マネージャが存在し、この参照に「完全な権限アクセス」がない場合、
checkPermission
メソッドが最初にコールされてRuntimePermission("defineClass")
がチェックされます。- パラメータ:
bytes
- クラス・バイト- 戻り値:
- クラスの
Class
オブジェクト - 例外:
IllegalAccessException
- このルックアップにPACKAGE
アクセスがない場合ClassFormatError
-bytes
がClassFile
構造でない場合IllegalArgumentException
-bytes
がルックアップ・クラスとは異なるパッケージ内のクラスを示している場合、またはbytes
がクラスまたはインタフェース(ACC_MODULE
フラグがaccess_flags
アイテムの値に設定されています)でない場合VerifyError
- 新しく作成したクラスを検証できない場合LinkageError
- 新しく作成されたクラスを他の理由でリンクできない場合SecurityException
- セキュリティ・マネージャが存在し、それがアクセスを拒否した場合NullPointerException
-bytes
がnull
の場合- 導入されたバージョン:
- 9
- 関連項目:
MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
,dropLookupMode(int)
,ClassLoader.defineClass(String,byte[],int,int,ProtectionDomain)
-
defineHiddenClass
public MethodHandles.Lookup defineHiddenClass(byte[] bytes, boolean initialize, MethodHandles.Lookup.ClassOption... options) throws IllegalAccessExceptionbytes
からhiddenクラスまたはインタフェースを作成し、新しく作成されたクラスまたはインタフェースにLookup
を返します。通常、クラスまたはインタフェース
C
は、C
を直接定義するか、別のクラス・ローダーに委譲するクラス・ローダーによって作成されます。 クラス・ローダーは、ClassLoader::defineClass
を起動してC
を直接定義します。これにより、Java Virtual Machineはclass
ファイル形式のパージされた表現からC
を導出します。 クラス・ローダーの使用が望ましくない場合は、かわりにこのメソッドでクラスまたはインタフェースC
を作成できます。 このメソッドは、ClassLoader::defineClass
を起動せずに、C
を定義して作成できます。 かわりに、このメソッドは、次のルールを使用して、Java Virtual Machineがclass
ファイル形式でパージされた表現から非配列クラスまたはインタフェースC
を導出するように配置することによって、C
を定義します:- この
Lookup
の「ルックアップ・モード」には、「完全な権限」アクセスが含まれている必要があります。 このアクセス・レベルは、このLookup
のルックアップ・クラスのモジュールにC
を作成するために必要です。 -
bytes
のパージされた表現は、サポートされているメジャーおよびマイナー・バージョンのClassFile
構造である必要があります。 メジャー・バージョンおよびマイナー・バージョンは、このLookup
のルックアップ・クラスのclass
ファイル・バージョンとは異なる場合があります。 -
this_class
の値はconstant_pool
表の有効な索引である必要があり、その索引のエントリは有効なCONSTANT_Class_info
構造である必要があります。N
を、この構造体で指定された内部形式でエンコードされたバイナリ名にします。N
は、ルックアップ・クラスと同じパッケージ内のクラスまたはインタフェースを示す必要があります。 -
CN
を文字列N + "." + <suffix>
にします。ここで、<suffix>
は非修飾名です。newBytes
を、constant_pool
表の追加エントリでbytes
によって指定されるClassFile
構造にし、CN
のCONSTANT_Utf8_info
構造体を示し、CONSTANT_Class_info
構造体がthis_class
によって示される新しいCONSTANT_Utf8_info
構造体を参照するようにします。L
をこのLookup
のルックアップ・クラスの定義クラス・ローダーにします。C
は、JVMS 5.3.5のルールと同様に、名前CN
、クラス・ローダーL
、およびパージされた表現newBytes
で導出されますが、次の調整があります:-
this_class
によって示される定数では、単一の"."
文字を含む名前を指定できます。ただし、これは内部形式の有効なバイナリ・クラスまたはインタフェース名ではありません。 - Java Virtual Machineは、
L
をC
の定義クラス・ローダーとしてマークしますが、C
の開始クラス・ローダーとして記録されるクラス・ローダーはありません。 -
C
は、このLookup
のルックアップ・クラスと同じランタイムpackage、moduleおよび「保護ドメイン」を持つとみなされます。 -
N
(内部形式でエンコードされたバイナリ名)を取得し、ASCIIフォワード・スラッシュをASCIIピリオドに置き換えることで、GN
を取得したバイナリ名にします。C
を表すClass
のインスタンスの場合:- これは有効なバイナリ・クラスまたはインタフェース名ではありませんが、
Class.getName()
は文字列GN + "/" + <suffix>
を返します。 - これは有効な型記述子名ではありませんが、
Class.descriptorString()
は文字列"L" + N + "." + <suffix> + ";"
を返します。 -
C
は「名目書式」で記述できないため、Class.describeConstable()
は空のオプションを返します。
- これは有効なバイナリ・クラスまたはインタフェース名ではありませんが、
-
C
は導出された後、Java Virtual Machineによってリンクされます。 JVMS 5.4.3で指定されているようにリンクが発生しますが、次の調整が行われます:- 検証中に、
CN
という名前のクラスをロードする必要がある場合は常に、試行が成功し、クラスC
が生成されます。 クラス・ローダーからのリクエストは行われません。 -
this_class
で示されたランタイム定数プールのエントリを解決しようとすると、シンボリック参照はC
に解決されたとみなされ、解決は常にすぐに成功します。
initialize
パラメータがtrue
の場合、C
はJava Virtual Machineによって初期化されます。新しく作成されたクラスまたはインタフェース
C
は、このメソッドによって返されるLookup
オブジェクトの「ルックアップ・クラス」として機能します。C
は、定数プール・エントリを介して他のクラスまたはインタフェースがC
を参照できないという意味でhiddenです。 つまり、非表示のクラスまたはインタフェースには、スーパータイプ、フィールド・タイプ、メソッド・パラメータ・タイプまたはメソッド戻り型として他のクラスで名前を付けることはできません。 これは、非表示のクラスまたはインタフェースにバイナリ名がないためであり、どのクラス定数プールにも記録できる内部形式がないためです。 非表示のクラスまたはインタフェースは、Class.forName(String, boolean, ClassLoader)
、ClassLoader.loadClass(String, boolean)
またはfindClass(String)
では検出できず、Javaエージェントまたは「JVMツール・インタフェース」を使用するツール・エージェントでは「変更可能」ではありません。「クラス・ローダー」によって作成されたクラスまたはインタフェースは、そのクラス・ローダーと強力な関係を持ちます。 つまり、すべての
Class
オブジェクトには、「定義済」が参照するClassLoader
への参照が含まれます。 つまり、クラス・ローダーによって作成されたクラスは、その定義ローダーに到達できず、ガベージ・コレクタ(JLS 12.7)によって再利用される可能性がある場合にのみアンロードできます。 ただし、デフォルトでは、非表示のクラスまたはインタフェースは、その定義ローダーとしてマークされているクラス・ローダーが「到達可能」であってもアンロードできます。 この動作は、非表示のクラスまたはインタフェースが、任意のクラス・ローダーによって定義された複数のクラスにサービスを提供する場合に便利です。 それ以外の場合、非表示のクラスまたはインタフェースは、非表示のクラスまたはインタフェースと同じ定義ローダーを持つ単一のクラス(または少数のクラス)にリンクできます。 このような場合、非表示のクラスまたはインタフェースが通常のクラスまたはインタフェースと一致する必要があるため、STRONG
オプションをoptions
で渡すことができます。 通常のクラスまたはインタフェースには独自の定義ローダーがあるため、非表示のクラスは、その定義ローダーとしてマークされたクラス・ローダーと同じ強力な関係を持つように配置されます。STRONG
が使用されていない場合でも、defineHiddenClass
の起動者は、Class
オブジェクトが到達可能であることを確認することで、非表示のクラスまたはインタフェースをアンロードできない場合があります。アンロード特性は、定義時に非表示クラスごとに設定され、後で変更することはできません。 定義ローダーとしてマークされたクラス・ローダーから独立して非表示クラスをアンロードできるという利点は、アプリケーションで非常に多くの非表示クラスを作成できることです。 対照的に、
STRONG
を使用すると、通常のクラスがクラス・ローダーによって作成された場合と同様に、JVMのメモリーが不足する可能性があります。ネスト内のクラスおよびインタフェースは、プライベート・メンバーへの相互アクセスを許可されます。 ネスト関係は、
class
ファイルのNestHost
属性(JVMS 4.7.28)およびNestMembers
属性(JVMS 4.7.29)によって決定されます。 非表示クラスにはバイナリ名がないため、デフォルトでは、非表示クラスはそれ自体のみで構成されるネストに属します。NESTMATE
オプションをoptions
に渡して、非表示のクラスまたはインタフェースC
をネストのメンバーとして作成できます。C
が属するネストは、C
が導出されたClassFile
構造のNestHost
属性に基づいていません。 かわりに、次のルールによってC
のネスト・ホストが決定されます:- この
Lookup
のルックアップ・クラスのネスト・ホストが以前に決定されている場合は、H
をルックアップ・クラスのネスト・ホストにします。 それ以外の場合は、JVMS 5.4.4のアルゴリズムを使用してルックアップ・クラスのネスト・ホストが決定され、H
が生成されます。 C
のネストされたホストは、ルックアップ・クラスのネストされたホストであるH
と判断されます。
非表示のクラスまたはインタフェースは直列化可能でもかまいませんが、インスタンスが適切にシリアライズおよび直列化復元されるようにするには、カスタム・シリアライズ・メカニズムが必要です。 デフォルトの直列化メカニズムでは、クラス名で検出可能なクラスおよびインタフェースのみがサポートされます。
- パラメータ:
bytes
- 「Java Virtual Machine仕様」で定義された有効なclass
ファイルの形式でクラス・データを構成するバイト。initialize
-true
の場合、そのクラスが初期化される。options
- 「クラス・オプション」- 戻り値:
- originalおよび「完全な権限」アクセス権を持つ非表示クラスの
Lookup
オブジェクト - 例外:
IllegalAccessException
- このLookup
に「完全な権限」アクセス権がない場合SecurityException
- セキュリティ・マネージャが存在し、それがアクセスを拒否した場合ClassFormatError
-bytes
がClassFile
構造でない場合UnsupportedClassVersionError
-bytes
がサポートされているメジャー・バージョンまたはマイナー・バージョンでない場合IllegalArgumentException
-bytes
がルックアップ・クラスとは異なるパッケージ内のクラスを示している場合、またはbytes
がクラスまたはインタフェース(ACC_MODULE
フラグがaccess_flags
アイテムの値に設定されています)でない場合IncompatibleClassChangeError
-C
の直接のスーパークラスとして指定されたクラスまたはインタフェースが実際にインタフェースである場合、またはC
の直接のスーパー・インタフェースとして指定されたクラスまたはインタフェースのいずれかが実際のインタフェースにない場合ClassCircularityError
-C
のスーパークラスまたはスーパー・インタフェースのいずれかがC
自体の場合VerifyError
- 新しく作成したクラスを検証できない場合LinkageError
- 新しく作成されたクラスを他の理由でリンクできない場合NullPointerException
- パラメータがnull
の場合- Java言語仕様を参照してください:
-
12.7 クラスおよびインタフェースのアンロード
- Java Virtual Machine仕様を参照してください:
-
4.2.1 バイナリ・クラス名およびインタフェース名
4.2.2 未修飾名
4.7.28NestHost
属性
4.7.29NestMembers
属性
5.4 .3.1 クラスおよびインタフェースの解決
5.4.4 アクセス制御
5.3.5class
ファイル表現からのClass
の導出
5.4 リンク
5.5 初期化 - 導入されたバージョン:
- 15
- 関連項目:
Class.isHidden()
- この
-
defineHiddenClassWithClassData
public MethodHandles.Lookup defineHiddenClassWithClassData(byte[] bytes, Object classData, boolean initialize, MethodHandles.Lookup.ClassOption... options) throws IllegalAccessException関連付けられた「クラス・データ」を使用してbytes
からhiddenクラスまたはインタフェースを作成し、新しく作成されたクラスまたはインタフェースでLookup
を返します。このメソッドは、クラス初期化子の最初の命令で指定された
classData
で初期化されたprivate static final 「名前なし」フィールドを非表示クラスに注入する場合と同様に、defineHiddenClass(bytes, initialize, options)
を呼び出すのと同じです。 新しく作成されたクラスは、Java Virtual Machineによってリンクされます。MethodHandles::classData
およびMethodHandles::classDataAt
メソッドを使用して、classData
を取得できます。- APIのノート:
- フレームワークでは、1つ以上のオブジェクトを含むクラス・データを持つ非表示クラスを作成し、ブートストラップ・メソッドを介して動的に計算された定数としてクラス・データをロードできます。
Class data
には、新しく定義された非表示クラスによって作成されたルックアップ・オブジェクトからのみアクセスできますが、同じネストされた(ネストしたユーザーがアクセスできるprivate staticフィールドとは異なります)内の他のメンバーからはアクセスできません。 クラス・データを介して配列やその他の可変構造体を渡す場合などは、可変性に注意してください。 クラス・データに格納されている値を実行時に変更すると、予期しない動作が発生する可能性があります。 クラス・データがList
の場合、たとえばList::of
を介して変更できないようにすることをお薦めします。 - パラメータ:
bytes
- クラス・バイトclassData
- 事前初期化されたクラス・データinitialize
-true
の場合、そのクラスが初期化される。options
- 「クラス・オプション」- 戻り値:
- originalおよび「完全な権限」アクセス権を持つ非表示クラスの
Lookup
オブジェクト - 例外:
IllegalAccessException
- このLookup
に「完全な権限」アクセス権がない場合SecurityException
- セキュリティ・マネージャが存在し、それがアクセスを拒否した場合ClassFormatError
-bytes
がClassFile
構造でない場合UnsupportedClassVersionError
-bytes
がサポートされているメジャー・バージョンまたはマイナー・バージョンでない場合IllegalArgumentException
-bytes
がルックアップ・クラスとは異なるパッケージ内のクラスを示している場合、またはbytes
がクラスまたはインタフェース(ACC_MODULE
フラグがaccess_flags
アイテムの値に設定されています)でない場合IncompatibleClassChangeError
-C
の直接のスーパークラスとして指定されたクラスまたはインタフェースが実際にインタフェースである場合、またはC
の直接のスーパー・インタフェースとして指定されたクラスまたはインタフェースのいずれかが実際のインタフェースにない場合ClassCircularityError
-C
のスーパークラスまたはスーパー・インタフェースのいずれかがC
自体の場合VerifyError
- 新しく作成したクラスを検証できない場合LinkageError
- 新しく作成されたクラスを他の理由でリンクできない場合NullPointerException
- パラメータがnull
の場合- Java言語仕様を参照してください:
-
「12.7 クラスおよびインタフェースのアンロード」
- Java Virtual Machine仕様を参照してください:
-
4.2.1 バイナリ・クラス名およびインタフェース名
4.2.2 未修飾名
4.7.28NestHost
属性
4.7.29NestMembers
属性
5.4 .3.1 クラスおよびインタフェースの解決
5.4.4 アクセス制御
5.3.5class
ファイル表現からのClass
の導出
5.4 リンク
5.5 初期化 - 導入されたバージョン:
- 16
- 関連項目:
defineHiddenClass(byte[], boolean, ClassOption...)
,Class.isHidden()
,MethodHandles.classData(Lookup, String, Class)
,MethodHandles.classDataAt(Lookup, String, Class, int)
-
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, IllegalAccessExceptionstaticメソッドのメソッド・ハンドルを生成します。 メソッド・ハンドルの型は、メソッドの型になります。 (staticメソッドはレシーバを取らないため、findVirtual
やfindSpecial
のように、メソッド・ハンドルの型に追加のレシーバ引数が挿入されることはありません。) このメソッドとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。返されるメソッド・ハンドルの引数が可変引数になるのは、メソッドの可変引数修飾子ビット(
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
-
ensureInitialized
public Class<?> ensureInitialized(Class<?> targetClass) throws IllegalAccessExceptiontargetClass
が初期化されていることを確認します。 初期化するクラスは、このLookup
オブジェクトへの「アクセシビリティ」である必要があります。 JVMS 5.5で指定されているように、targetClass
が初期化されていない場合は、このメソッドによって初期化されます。- パラメータ:
targetClass
- 初期化されるクラス- 戻り値:
- 初期化された
targetClass
- 例外:
IllegalArgumentException
-targetClass
がプリミティブ型、void
または配列クラスの場合IllegalAccessException
-targetClass
がこのルックアップに対する「アクセシビリティ」でない場合ExceptionInInitializerError
- このメソッドによって起動されたクラスの初期化が失敗した場合SecurityException
- セキュリティ・マネージャが存在し、それがアクセスを拒否した場合- Java Virtual Machine仕様を参照してください:
-
5.5 初期化
- 導入されたバージョン:
- 15
-
accessClass
public Class<?> accessClass(Class<?> targetClass) throws IllegalAccessExceptionこのLookup
オブジェクトによって定義されたルックアップ・コンテキストからクラスにアクセスできるかどうかを判定します。 クラスの静的初期化子は実行されません。targetClass
が参照クラスと同じモジュールにある場合、その参照クラスはモジュールM1
のLC
になり、前の参照クラスがモジュールM0
またはnull
にある場合、targetClass
は、次のいずれかがtrueである場合にのみアクセス可能です:- この参照に
PRIVATE
アクセス権がある場合、targetClass
はLC
の同じネストに含まれているLC
または他のクラスです。 - この参照に
PACKAGE
アクセス権がある場合、targetClass
はLC
の同じランタイム・パッケージに含まれます。 - この参照に
MODULE
アクセス権がある場合、targetClass
はM1
の公開タイプです。 - この参照に
PUBLIC
アクセス権がある場合、targetClass
は、以前の参照クラスが存在する場合に少なくともM0
にエクスポートされるパッケージのパブリック・タイプです。それ以外の場合、targetClass
はM1
で無条件にエクスポートされたパッケージ内のパブリック・タイプです。
そうでない場合、この参照に
UNCONDITIONAL
アクセス権が含まれていると、タイプが無条件でエクスポートされたパッケージの場合、この参照ではすべてのモジュールの公開タイプにアクセスできます。それ以外の場合、ターゲット・クラスは
lookupClass
と異なるモジュールにあり、この参照にPUBLIC
アクセスがない場合、lookupClass
にはアクセスできません。それ以外の場合でこの参照に「前のルックアップ・クラス」が含まれない場合、
M1
はlookupClass
を含むモジュール、M2
はtargetClass
を含むモジュールであり、次の場合にのみtargetClass
にアクセスできますM1
はM2
を読み取り、targetClass
はパブリックで、M2
によって少なくともM1
にエクスポートされたパッケージ内にあります。
それ以外の場合で、この参照に「前のルックアップ・クラス」、
M1
およびM2
が以前と同様であり、M0
が以前の参照クラスを含むモジュールである場合、targetClass
は次のいずれかがtrueである場合にのみアクセス可能です:targetClass
はM0
にあり、M1
はM0
を読み取り、タイプは少なくともM1
にエクスポートされるパッケージ内にあります。targetClass
はM1
にあり、M0
はM1
を読み取り、タイプは少なくともM0
にエクスポートされるパッケージ内にあります。targetClass
は3つ目のモジュールM2
に含まれ、M0
とM1
は両方ともM2
を読み取り、タイプは少なくともM0
とM2
の両方にエクスポートされるパッケージに含まれます。
それ以外の場合、
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
と宣言されている場合、書き込み、アトミック更新、数値アトミック更新、ビット単位アトミック更新アクセス・モードはサポートされません。 - フィールド型が
byte
、short
、char
、int
、long
、float
、またはdouble
以外の場合、数値アトミック更新アクセス・モードはサポートされていません。 - フィールド型が
boolean
、byte
、short
、char
、int
または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, IllegalAccessExceptionstaticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。 メソッド・ハンドルの型に含まれる戻り値の型は、フィールドの値の型になります。 メソッド・ハンドルは引数を一切取りません。 ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。返されるメソッド・ハンドルが呼び出された場合、そのフィールドのクラスは初期化されます(まだ初期化されていない場合)。
- パラメータ:
refc
- メソッドのアクセス元となるクラスまたはインタフェースname
- フィールドの名前type
- フィールドの型- 戻り値:
- フィールドから値をロードできるメソッド・ハンドル
- 例外:
NoSuchFieldException
- フィールドが存在しない場合IllegalAccessException
- アクセス・チェックが失敗した場合、またはフィールドがstatic
でない場合SecurityException
- セキュリティ・マネージャが存在し、それがアクセスを拒否した場合NullPointerException
- いずれかの引数がnullの場合
-
findStaticSetter
public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessExceptionstaticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。 このメソッド・ハンドルの型に含まれる戻り値の型は、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
と宣言されている場合、書き込み、アトミック更新、数値アトミック更新、ビット単位アトミック更新アクセス・モードはサポートされません。 - フィールド型が
byte
、short
、char
、int
、long
、float
、またはdouble
以外の場合、数値アトミック更新アクセス・モードはサポートされていません。 - フィールド型が
boolean
、byte
、short
、char
、int
または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;
defc
はreceiver.getClass()
またはそのクラスのスーパー・タイプのいずれかであり、その中では、要求されたメソッドにルックアップ・クラスからアクセスできます。 (bind
とは異なり、bindTo
は可変アリティを保持しません。 また、bindTo
は、メンバーがprotected
であり、レシーバがfindVirtual
によってルックアップ・クラスに制限されている場合のように、bind
がIllegalAccessException
をスローするインスタンスで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
メソッドへの対応するコールが正常に返された場合のみです。 具体的には、static
とfinal
の両方であるフィールドを設定しない場合があります。フィールドが
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
と宣言されている場合、書き込み、アトミック更新、数値アトミック更新、ビット単位アトミック更新アクセス・モードはサポートされません。 - フィールド型が
byte
、short
、char
、int
、long
、float
、またはdouble
以外の場合、数値アトミック更新アクセス・モードはサポートされていません。 - フィールド型が
boolean
、byte
、short
、char
、int
または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()非推奨。このメソッドは、当初は、完全な権限アクセスを意味するPRIVATE
アクセスをテストするように設計されましたが、MODULE
アクセスはPRIVATE
アクセスから独立しているためです。hasFullPrivilegeAccess()
を呼び出すことをお薦めします。この参照にPRIVATE
およびMODULE
アクセス権がある場合はtrue
を返します。- 戻り値:
- この参照に
PRIVATE
およびMODULE
アクセス権がある場合、true
。 - 導入されたバージョン:
- 9
-
hasFullPrivilegeAccess
public boolean hasFullPrivilegeAccess()この参照にPRIVATE
およびMODULE
アクセス権などの「完全な権限アクセス」がある場合、true
を返します。 「ルックアップ・クラス」にアクセス可能なすべてのメンバーにアクセスするには、Lookup
オブジェクトへの完全なアクセス権限が必要です。- 戻り値:
- この参照に完全な権限アクセスがある場合、
true
。 - 導入されたバージョン:
- 14
- 関連項目:
- プライベートおよびモジュール・アクセス
-
PRIVATE
アクセスをテストするように設計されましたが、MODULE
アクセスはPRIVATE
アクセスから独立しているためです。