- 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)staticFT f;(T) C.f;lookup.findSetter(C.class,"f",FT.class)FT f;this.f = x;lookup.findStaticSetter(C.class,"f",FT.class)staticFT f;C.f = arg;lookup.findVirtual(C.class,"m",MT)T m(A*);(T) this.m(arg*);lookup.findStatic(C.class,"m",MT)staticT 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.unreflect(aMethod)( static)?T m(A*);(T) aMethod.invoke(thisOrNull, 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は、指定されたメンバーに対応するリフレクション・オブジェクトを表しています。findClass操作のバイトコード動作は、ldc CONSTANT_Classの場合と同様に、定数クラスのロードです。 振る舞いは、メソッド・ハンドルとしてではなく、直接Class定数として表されます。指定されたメンバーが可変引数(つまりメソッドまたはコンストラクタ)の場合、返されるメソッド・ハンドルも可変引数になります。 その他のすべての場合、返されるメソッド・ハンドルは固定引数になります。
ディスカッション: ルックアップされたメソッド・ハンドルと基礎となるクラス・メンバーとバイトコード動作との間の等価性が、いくつかの方法で壊れることがあります。
Cがルックアップ・クラスのローダーからシンボルでアクセスできない場合でも、ルックアップが成功することがあります(同等のJava式やバイト・コード定数が存在しない場合でも)。- 同様に、
TまたはMTがルックアップ・クラスのローダーからシンボルでアクセスできない場合でも、ルックアップが成功することがあります。 たとえば、MethodHandle.invokeExactやMethodHandle.invokeのルックアップは、要求された型とは無関係に常に成功します。 - セキュリティ・マネージャがインストールされている場合、さまざまな理由でルックアップが禁止される可能性があります(以下を参照)。 一方、
CONSTANT_MethodHandle定数でのldc命令はセキュリティ・マネージャ・チェックされません。 - ルックアップされるメソッドが非常に大きな引数カウントを持つ場合、メソッド・ハンドル型が持つパラメータが多すぎるためにメソッド・ハンドル作成に失敗する場合があります。
アクセス・チェック
アクセス・チェックは、メソッド・ハンドルの作成時にLookupのファクトリ・メソッド内で適用されます。 これが、Core Reflection APIとの重要な違いです(java.lang.reflect.Method.invokeではすべての呼出しで、すべての呼出し元に対してアクセス・チェックが実行される)。すべてのアクセス・チェックは
Lookupオブジェクトから始まりますが、このオブジェクトでは、記録されているルックアップ・クラスとすべてのメソッド・ハンドル作成要求とが照合されます。 単一のLookupオブジェクトを使って任意の数のアクセス・チェック済みメソッド・ハンドルを作成できます(すべては単一のルックアップ・クラスに基づいてチェックされる)。Lookupオブジェクトは、ほかの信頼できるコード(メタオブジェクト・プロトコルなど)と共有できます。 共有Lookupオブジェクトは、メソッド・ハンドルを作成する機能を、ルックアップ・クラスのprivateメンバーに委譲します。 特権付きコードがLookupオブジェクトを使用する場合でも、アクセス・チェックは元のルックアップ・クラスの特権に限定されます。ルックアップが失敗することがあります。包含するクラスにルックアップ・クラスからアクセスできない、目的のクラス・メンバーが見つからない、目的のクラス・メンバーにルックアップ・クラスからアクセスできない、またはルックアップ・オブジェクトが信頼されていないためメンバーにアクセスためです。 いずれの場合も、試みられたルックアップから
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を生成します。場合によっては、ネストされたクラス間のアクセスは、Javaコンパイラが、別のクラスのprivateメソッドにアクセスするためのラッパー・メソッドを同じトップ・レベルの宣言内で作成することによって得られます。 たとえば、ネストされたクラス
C.Dはほかの関連クラス(C、C.D.E、C.Bなど)の内部のprivateメンバーにアクセスできますが、Javaコンパイラがそれらの関連クラス内でラッパー・メソッドを生成しなければいけない可能性があります。 そのような場合、C.EのLookupオブジェクトはそれらのprivateメンバーにアクセスできません。 この制限の回避方法の1つがLookup.inメソッドであり、これを使うことで、特権レベルを特別に上げることなくC.Eのルックアップをそうしたほかのクラスのいずれかのルックアップに変換できます。指定されたルックアップ・オフセットに許可されるアクセスは、その
lookupModesセットに基づいて、ルックアップ・クラスから通常アクセスできるメンバー・サブセットに制限される場合があります。 たとえば、publicLookupメソッドは、エクスポートされたパッケージのパブリック・クラスのパブリック・メンバーにのみアクセスできるルックアップ・オブジェクトを生成します。 呼出し元依存メソッドlookupは、サポートされているすべてのバイトコード動作をエミュレートする、呼出し元クラスに関連するあらゆる機能を持つルックアップ・オブジェクトを生成します。 また、Lookup.inメソッドは元のルックアップ・オブジェクトよりアクセス・モードが少ないルックアップ・オブジェクトを生成できます。privateアクセスのディスカッション: ルックアップ・モードに
privateメンバーにアクセスする可能性が含まれる場合、そのルックアップはprivateアクセスを持つと言います。 ドキュメント内の関連メソッドに記述されているように、privateアクセスを持つルックアップのみが次の機能を持ちます。- ルックアップ・クラスのprivateフィールド、メソッド、およびコンストラクタにアクセスする
- 呼出し元依存メソッド(
Class.forNameなど)を呼び出すメソッド・ハンドルを作成する invokespecial命令をエミュレートするメソッド・ハンドルを作成する- ルックアップ・クラスからアクセスできるクラスに対するパッケージ・アクセス・チェックを回避する
- 同じパッケージ・メンバー内の他のクラスに対するprivateアクセスを持つ、
委譲されたルックアップ・オブジェクトを作成する
これらのことが許可されるのは、privateアクセスを持つルックアップ・オブジェクトから元のクラスまで安全にたどることができ、そのバイトコード動作およびJava言語アクセス権をメソッド・ハンドルが確実に判断してエミュレートできるという事実の結果です。
セキュリティ・マネージャとの対話
バイト・コード命令は関連クラス・ローダー内のクラスしか参照できませんが、このAPIでは、Classオブジェクトへの参照が使用可能であるかぎり、任意のクラス内のメソッドを検索できます。 そのようなクロスローダー参照は、Core Reflection APIでも可能ですが、invokestaticやgetfieldなどのバイト・コード命令では不可能です。 アプリケーション内でそのようなクロスローダー参照をチェックできるようにするためのセキュリティ・マネージャAPIが存在します。 それらのチェックは、MethodHandles.LookupAPIと(Class上に存在する) Core Reflection APIの両方に適用されます。セキュリティ・マネージャが存在する場合、メンバーおよびクラスのルックアップは追加検査の対象となります。 セキュリティ・マネージャに対して1回から3回の呼出しが行われます。 これらの呼出しのいずれも、
SecurityExceptionをスローすることでアクセスを拒否できます。smgrをセキュリティ・マネージャとして、lookcを現在のルックアップ・オブジェクトのルックアップ・クラスとして、refcをメンバーを検索する包含クラスとして、defcをメンバーが実際に定義されるクラスとして定義してください。 (クラスまたは他の型がアクセスされている場合、refcおよびdefcの値はクラスそのものです。) 値lookcは、現在のルックアップ・オブジェクトがprivateアクセスを持たない場合は存在しないとして定義されます。 次のルールに従って呼出しが行われます。- ステップ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のパッケージ)。
呼出し元依存メソッド
少数のJavaメソッドに、呼出し元依存性という特殊なプロパティがあります。 呼出し元依存メソッドは、その直接の呼出し元の識別情報によって異なる動作をする可能性があります。呼出し元依存メソッドのメソッド・ハンドルが要求された場合は、バイトコード動作の一般ルールが適用されますが、ルックアップ・クラスは特別な方法で考慮されます。 結果のメソッド・ハンドルはルックアップ・クラスに含まれている命令から呼び出されたように動作し、呼出し元依存メソッドはルックアップ・クラスを検出します。 (一方、メソッド・ハンドルのインボーカは無視されます。) したがって、呼出し元依存メソッドの場合は、ルックアップ・クラスごとにメソッド・ハンドルの動作が異なる可能性があります。
ルックアップ・オブジェクトが
publicLookup()の場合、またはprivateアクセスなしのいくつかの他のルックアップ・オブジェクトの場合、そのルックアップ・クラスは無視されます。 そのような場合、呼出し元依存メソッド・ハンドルを作成できず、アクセスは禁止され、ルックアップはIllegalAccessExceptionで失敗します。ディスカッション: たとえば、呼出し元依存メソッド
Class.forName(x)は、それを呼び出すクラスのクラス・ローダーに応じて、返されるクラスを異なったり、スローされる例外が異なったりする可能性があります。Class.forNameのpublicルックアップは失敗します。そのバイトコード動作を判別するための妥当な方法がないためです。広範囲な共有のためにメソッド・ハンドルをキャッシュするアプリケーションの場合は、
publicLookup()を使用してメソッド・ハンドルを作成することをお薦めします。Class.forNameのルックアップがある場合、それは失敗し、アプリケーションはその場合に適切なアクションを取る必要があります。 たとえば、後のルックアップ(おそらくブートストラップ・メソッドの呼び出し中)が呼出し元固有の識別情報を組み込むことで、メソッドをアクセス可能にするアクションです。関数
MethodHandles.lookupは呼出し元依存なので、ルックアップ用の安全な基盤が存在できます。 JSR 292 API内の他のほとんどすべてのメソッドはルックアップ・オブジェクトに依存してアクセス要求をチェックします。
-
-
フィールドのサマリー
フィールド 修飾子と型 フィールド 説明 static intMODULEmoduleを表す単一ビットのマスク(デフォルト・アクセス)は、lookupModesの結果に寄与する可能性があります。static intPACKAGEpackageアクセス(デフォルト・アクセス)を表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。static intPRIVATEprivateアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。static intPROTECTEDprotectedアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。static intPUBLICpublicアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。static intUNCONDITIONALunconditionalアクセスを表す1ビット・マスクで、lookupModesの結果に寄与する可能性があります。
-
メソッドのサマリー
すべてのメソッド インスタンス・メソッド 具象メソッド 修飾子と型 メソッド 説明 Class<?>accessClass(Class<?> targetClass)このLookupオブジェクトによって定義されたルックアップ・コンテキストからクラスにアクセスできるかどうかを判定します。MethodHandlebind(Object receiver, String name, MethodType type)非staticメソッドの早期バインド・メソッド・ハンドルを生成します。Class<?>defineClass(byte[] bytes)クラスを同じクラス・ローダーと同じランタイム・パッケージに定義し、「保護ドメイン」をこのルックアップ「ルックアップ・クラス」として定義します。MethodHandles.LookupdropLookupMode(int modeToDrop)このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。Class<?>findClass(String targetName)このLookupオブジェクトによって定義されたルックアップ・コンテキストからクラスを名前で検索します。MethodHandlefindConstructor(Class<?> refc, MethodType type)指定された型のコンストラクタを使ってオブジェクトの作成と初期化を行うメソッド・ハンドルを生成します。MethodHandlefindGetter(Class<?> refc, String name, Class<?> type)非staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。MethodHandlefindSetter(Class<?> refc, String name, Class<?> type)非staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。MethodHandlefindSpecial(Class<?> refc, String name, MethodType type, Class<?> specialCaller)仮想メソッドの早期にバインドされるメソッド・ハンドルを生成します。MethodHandlefindStatic(Class<?> refc, String name, MethodType type)staticメソッドのメソッド・ハンドルを生成します。MethodHandlefindStaticGetter(Class<?> refc, String name, Class<?> type)staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。MethodHandlefindStaticSetter(Class<?> refc, String name, Class<?> type)staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。VarHandlefindStaticVarHandle(Class<?> decl, String name, Class<?> type)型declのクラスで宣言された型typeの静的フィールドnameへのアクセスを提供するVarHandleを生成します。VarHandlefindVarHandle(Class<?> recv, String name, Class<?> type)型recvのクラスで宣言された型typeの非静的フィールドnameへのアクセスを提供するVarHandleを生成します。MethodHandlefindVirtual(Class<?> refc, String name, MethodType type)仮想メソッドのメソッド・ハンドルを生成します。booleanhasPrivateAccess()このルックアップにPRIVATEアクセスがある場合は、trueを返します。MethodHandles.Lookupin(Class<?> requestedLookupClass)指定された新しいルックアップ・クラスでルックアップを作成します。Class<?>lookupClass()ルックアップを実行しているクラスを示します。intlookupModes()このルックアップ・オブジェクトがどのアクセス保護クラスのメンバーを生成できるかを示します。MethodHandleInforevealDirect(MethodHandle target)この参照オブジェクトまたは類似のオブジェクトによって作成された直接メソッド・ハンドルを解読します。StringtoString()ルックアップの実行元となるクラスの名前を表示します。MethodHandleunreflect(Method m)ルックアップ・クラスがアクセス権を持つ場合に、mへの直接メソッド・ハンドルを作成します。MethodHandleunreflectConstructor(Constructor<?> c)リフレクトされたコンストラクタのメソッド・ハンドルを生成します。MethodHandleunreflectGetter(Field f)リフレクトされたフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。MethodHandleunreflectSetter(Field f)リフレクトされたフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。MethodHandleunreflectSpecial(Method m, Class<?> specialCaller)リフレクトされたメソッドのメソッド・ハンドルを生成します。VarHandleunreflectVarHandle(Field f)クラスRで宣言されたT型の反映されたフィールドfへのアクセスを提供するVarHandleを生成します。
-
-
-
フィールドの詳細
-
PUBLIC
public static final int PUBLIC
publicアクセスを表す単一ビット・マスク(lookupModesの結果に寄与する可能性がある)。 値0x01はたまたま、public修飾子ビットの値と同じになっています。- 関連項目:
- 定数フィールド値
-
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は、ルックアップ・クラスのモジュール内のすべてのパブリック型と、他のモジュールによってルックアップ・クラスのモジュールにエクスポートされたパブリック型にアクセスできます。- 導入されたバージョン:
- 9
- 関連項目:
- 定数フィールド値
-
UNCONDITIONAL
public static final int UNCONDITIONAL
unconditionalアクセスを表す1ビット・マスクで、lookupModesの結果に寄与する可能性があります。 値は0x20です。これは特定の「修飾子ビット」には意味がありません。 このルックアップ・モードのLookupはreadabilityを想定しています。PUBLIC修飾子ビットと組み合わせて、このルックアップ・モードを持つLookupは、型がパッケージ内のexported unconditionallyであるすべてのモジュールのパブリック型のすべてのパブリック・メンバーにアクセスできます。- 導入されたバージョン:
- 9
- 関連項目:
MethodHandles.publicLookup(), 「定数フィールド値」
-
-
メソッドの詳細
-
lookupClass
public Class<?> lookupClass()
ルックアップを実行しているクラスを示します。 可視性やアクセス権のチェックが実行されるのは、このクラスに対してです。このクラスは最大レベルのアクセス権を暗黙的に示しますが、非publicメンバーにアクセスできるかどうかを制御するビット・マスク
lookupModesにより、アクセス権がさらに制限される可能性もあります。- 戻り値:
- ルックアップ・クラス、これのためにこのルックアップ・オブジェクトはメンバーを探す
-
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オブジェクトは、元のオブジェクトと同等以下のアクセス機能しか持たないことが保証されます。 具体的には、アクセス機能が次のように失われる可能性があります。- 古いルックアップ・クラスが
namedモジュールにあり、新しいルックアップ・クラスが別のモジュールMにある場合、Mエクスポートされたパッケージ内のパブリック・メンバーでなく、メンバーにアクセスすることはできません。 例外は、このルックアップがpublicLookupの場合です。この場合、PUBLICアクセスは失われません。 - 古いルックアップ・クラスが名前のないモジュールにあり、新しいルックアップ・クラスが別のモジュールである場合、
MODULEアクセスは失われます。 - 新しいルックアップ・クラスが古いルックアップ・クラスと異なる場合、
UNCONDITIONALは失われます。 - 新しいルックアップ・クラスが古いクラスとは異なるパッケージ内に存在している場合、protectedメンバーとデフォルト(package)メンバーにアクセスできません。
- 新しいルックアップ・クラスが古いものと同じパッケージ・メンバー内にない場合、プライベート・メンバーにアクセスできなくなり、保護されたメンバーは継承のためにアクセスできなくなります。 (パッケージ共有のため、protectedメンバーに引き続きアクセスできる場合もあります。)
- 古いルックアップ・クラスから新しいルックアップ・クラスにアクセスできない場合、publicメンバーも含め、すべてのメンバーにアクセスできません。 (その他のすべての場合には、publicメンバーに引き続きアクセスできます。)
クラス(
findClass(java.lang.String)呼び出し中に使用される)をロードするために結果として得られるルックアップ機能は、ルックアップ・クラスのローダーによって決定されます。このローダーは、この操作によって変更される可能性があります。- パラメータ:
requestedLookupClass- 新しいルックアップ・オブジェクト用に要求されるルックアップ・クラス- 戻り値:
- 目的のルックアップ・クラスを報告するルックアップ・オブジェクト、または変更がなければ同じオブジェクト
- 例外:
NullPointerException- 引数がnullの場合
- 古いルックアップ・クラスが
-
dropLookupMode
public MethodHandles.Lookup dropLookupMode(int modeToDrop)
このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。 ドロップするルックアップ・モードは、PUBLIC、MODULE、PACKAGE、PROTECTEDまたはPRIVATEのいずれかです。PROTECTEDとUNCONDITIONALは常に削除されるため、結果のルックアップ・モードではこれらのアクセス機能は使用できません。PACKAGEを削除すると、結果のルックアップにはPACKAGEまたはPRIVATEアクセスがありません。MODULEをドロップすると、結果のルックアップにはMODULE、PACKAGE、またはPRIVATEアクセスがありません。PUBLICがドロップされた場合、結果のルックアップにはアクセス権がありません。- パラメータ:
modeToDrop- ルックアップ・モードをドロップ- 戻り値:
- 示されたモードを持たない参照オブジェクト、または変更がなければ同じオブジェクト
- 例外:
IllegalArgumentException-modeToDropがPUBLIC、MODULE、PACKAGE、PROTECTED、PRIVATEまたは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仮想マシン仕様」で定義されている)のクラス・バイトです。このメソッドは、クラス初期化子を実行しません。 クラス初期化子は、「Java言語仕様」のセクション12.4で詳しく説明するように、後で実行することができます。
セキュリティ・マネージャがある場合は、最初に
checkPermissionメソッドを呼び出してRuntimePermission("defineClass")をチェックします。- パラメータ:
bytes- クラス・バイト- 戻り値:
- クラスの
Classオブジェクト - 例外:
IllegalArgumentException- バイトはルックアップ・クラスとは異なるパッケージ内のクラス用ですIllegalAccessException- このルックアップにPACKAGEアクセスがない場合LinkageError- クラスが不正な形式(ClassFormatError)であるか、(VerifyError)であるか、(VerifyError)であるか、すでに定義されているか、別のリンク・エラーが発生した場合SecurityException- セキュリティ・マネージャによって拒否された場合NullPointerException-bytesがnullの場合- 導入されたバージョン:
- 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」になります。
- エクスポートされたパッケージの型へのパブリック・アクセスのみが許可されている場合、サフィクスは"/public"です。
- パブリック・アクセスと無条件アクセスのみが許可されている場合、サフィクスは"/publicLookup"です。
- パブリック・アクセスとモジュール・アクセスのみが許可されている場合、サフィクスは"/module"です。
- パブリック、モジュール、およびパッケージのアクセスのみが許可されている場合、サフィクスは"/package"です。
- public、module、package、およびprivateアクセスのみが許可されている場合、サフィクスは"/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メソッドはレシーバを取らないため、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)を追加したものになります。 このメソッドとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。ハンドルは呼出し時に、最初の引数をレシーバとみなし、そのレシーバの型でディスパッチしてどのメソッド実装に入るかを決定します。 (このディスパッチ・アクションは、
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の場合、またはメソッドがprivateインタフェースのメソッドである場合、またはメソッド可変アリティ修飾子ビットがセットされ、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オブジェクトによって定義されたルックアップ・コンテキストからクラスを名前で検索します。 クラスの静的初期化子は実行されません。ここでのルックアップ・コンテキストは、「ルックアップ・クラス」、そのクラス・ローダー、および「ルックアップ・モード」によって決定されます。 具体的には、このメソッドは、最初にリクエストされたクラスをロードしようとし、そのクラスがこのルックアップ・オブジェクトにアクセス可能であるかどうかを判定します。
- パラメータ:
targetName- 参照されるクラスの完全修飾名。- 戻り値:
- リクエストされたクラス。
- 例外:
SecurityException- セキュリティ・マネージャが存在し、それがアクセスを拒否した場合LinkageError- リンケージに失敗した場合ClassNotFoundException- ルックアップ・クラス・ローダーによってクラスをロードできない場合。IllegalAccessException- クラスにアクセスできない場合は、許可されたアクセス・モードを使用します。SecurityException- セキュリティ・マネージャが存在し、それがアクセスを拒否した場合- 導入されたバージョン:
- 9
-
accessClass
public Class<?> accessClass(Class<?> targetClass) throws IllegalAccessException
このLookupオブジェクトによって定義されたルックアップ・コンテキストからクラスにアクセスできるかどうかを判定します。 クラスの静的初期化子は実行されません。ここでのルックアップ・コンテキストは、「ルックアップ・クラス」と「ルックアップ・モード」によって決まります。
- パラメータ:
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の場合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, 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でない場合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の場合、メソッド・ハンドルは引数を一切取りません。 それ以外の場合、その単一の引数は、フィールドを含むインスタンスになります。 フィールドのaccessibleフラグが設定されていない場合、ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。フィールドがstaticで、返されるメソッド・ハンドルが呼び出された場合、そのフィールドのクラスは初期化されます(まだ初期化されていない場合)。
- パラメータ:
f- リフレクトされたフィールド- 戻り値:
- リフレクトされたフィールドから値をロードできるメソッド・ハンドル
- 例外:
IllegalAccessException- アクセス・チェックが失敗した場合NullPointerException- 引数がnullの場合
-
unreflectSetter
public MethodHandle unreflectSetter(Field f) throws IllegalAccessException
リフレクトされたフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。 このメソッド・ハンドルの型に含まれる戻り値の型は、voidになります。 フィールドがstaticの場合、メソッド・ハンドルはフィールドの値の型を持つ単一の引数(格納する値)を取ります。 それ以外の場合、2つの引数は、フィールドを含むインスタンスと格納する値になります。 フィールドのaccessibleフラグが設定されていない場合、ルックアップ・クラスに代わって即座にアクセス・チェックが実行されます。フィールドがstaticで、返されるメソッド・ハンドルが呼び出された場合、そのフィールドのクラスは初期化されます(まだ初期化されていない場合)。
- パラメータ:
f- リフレクトされたフィールド- 戻り値:
- リフレクトされたフィールドに値を格納できるメソッド・ハンドル
- 例外:
IllegalAccessException- アクセス・チェックが失敗した場合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
public boolean hasPrivateAccess()
このルックアップにPRIVATEアクセスがある場合は、trueを返します。- 戻り値:
- このルックアップに
PRIVATEアクセスがある場合はtrue。 - 導入されたバージョン:
- 9
-
-