- java.lang.Object
-
- java.lang.invoke.MethodHandles.Lookup
-
- 含まれているクラス:
- MethodHandles
public static final class MethodHandles.Lookup extends Object
ルックアップ・オブジェクトは、メソッド・ハンドルの作成にアクセス・チェックが必要な場合のメソッド・ハンドル作成用ファクトリです。 メソッド・ハンドルでアクセス・チェックが実行されるのは、その呼出し時ではなく作成時です。 したがって、メソッド・ハンドルのアクセス制限は、メソッド・ハンドルの作成時に適用する必要があります。 それらの制限の適用先となる呼出し元クラスは、ルックアップ・クラスと呼ばれます。メソッド・ハンドルを作成する必要のあるルックアップ・クラスは、
MethodHandles.lookup
を呼び出して自分用のファクトリを作成します。Lookup
ファクトリ・オブジェクトの作成時には、ルックアップ・クラスのアイデンティティが決定され、その情報がLookup
オブジェクト内にセキュアに格納されます。 その後、ルックアップ・クラス(またはその委譲先)は、Lookup
オブジェクトのファクトリ・メソッドを使ってアクセス・チェックされたメンバーのメソッド・ハンドルを作成できます。 これには、ルックアップ・クラスに許可されるメソッド、コンストラクタ、およびフィールドがすべて含まれます(privateのものも含む)。Lookupファクトリ・メソッド
Lookup
オブジェクトのファクトリ・メソッドは、メソッド、コンストラクタ、およびフィールドのすべてのメジャーなユース・ケースに対応しています。 ファクトリ・メソッドによって作成される各メソッド・ハンドルは、特定のバイトコード動作と機能的に同等です。 (バイトコード動作は『Java Virtual Machine Specification』のセクション5.4.3.5に記述されています。) これらのファクトリ・メソッドと、結果として得られるメソッド・ハンドルの動作との対応の概要を以下に示します:ルックアップ式 メンバー バイトコード動作 lookup.findGetter(C.class,"f",FT.class)
FT f;
(T) this.f;
lookup.findStaticGetter(C.class,"f",FT.class)
static
FT f;
(T) 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.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.Lookup
APIと(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 int
MODULE
module
を表す単一ビットのマスク(デフォルト・アクセス)は、lookupModes
の結果に寄与する可能性があります。static int
PACKAGE
package
アクセス(デフォルト・アクセス)を表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
PRIVATE
private
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
PROTECTED
protected
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
PUBLIC
public
アクセスを表す単一ビット・マスク(lookupModes
の結果に寄与する可能性がある)。static int
UNCONDITIONAL
unconditional
アクセスを表す1ビット・マスクで、lookupModes
の結果に寄与する可能性があります。
-
メソッドのサマリー
すべてのメソッド インスタンス・メソッド 具象メソッド 修飾子と型 メソッド 説明 Class<?>
accessClass(Class<?> targetClass)
このLookup
オブジェクトによって定義されたルックアップ・コンテキストからクラスにアクセスできるかどうかを判定します。MethodHandle
bind(Object receiver, String name, MethodType type)
非staticメソッドの早期バインド・メソッド・ハンドルを生成します。Class<?>
defineClass(byte[] bytes)
クラスを同じクラス・ローダーと同じランタイム・パッケージに定義し、「保護ドメイン」をこのルックアップ「ルックアップ・クラス」として定義します。MethodHandles.Lookup
dropLookupMode(int modeToDrop)
このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。Class<?>
findClass(String targetName)
このLookup
オブジェクトによって定義されたルックアップ・コンテキストからクラスを名前で検索します。MethodHandle
findConstructor(Class<?> refc, MethodType type)
指定された型のコンストラクタを使ってオブジェクトの作成と初期化を行うメソッド・ハンドルを生成します。MethodHandle
findGetter(Class<?> refc, String name, Class<?> type)
非staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。MethodHandle
findSetter(Class<?> refc, String name, Class<?> type)
非staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。MethodHandle
findSpecial(Class<?> refc, String name, MethodType type, Class<?> specialCaller)
仮想メソッドの早期にバインドされるメソッド・ハンドルを生成します。MethodHandle
findStatic(Class<?> refc, String name, MethodType type)
staticメソッドのメソッド・ハンドルを生成します。MethodHandle
findStaticGetter(Class<?> refc, String name, Class<?> type)
staticフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。MethodHandle
findStaticSetter(Class<?> refc, String name, Class<?> type)
staticフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。VarHandle
findStaticVarHandle(Class<?> decl, String name, Class<?> type)
型decl
のクラスで宣言された型type
の静的フィールドname
へのアクセスを提供するVarHandleを生成します。VarHandle
findVarHandle(Class<?> recv, String name, Class<?> type)
型recv
のクラスで宣言された型type
の非静的フィールドname
へのアクセスを提供するVarHandleを生成します。MethodHandle
findVirtual(Class<?> refc, String name, MethodType type)
仮想メソッドのメソッド・ハンドルを生成します。boolean
hasPrivateAccess()
このルックアップにPRIVATE
アクセスがある場合は、true
を返します。MethodHandles.Lookup
in(Class<?> requestedLookupClass)
指定された新しいルックアップ・クラスでルックアップを作成します。Class<?>
lookupClass()
ルックアップを実行しているクラスを示します。int
lookupModes()
このルックアップ・オブジェクトがどのアクセス保護クラスのメンバーを生成できるかを示します。MethodHandleInfo
revealDirect(MethodHandle target)
この参照オブジェクトまたは類似のオブジェクトによって作成された直接メソッド・ハンドルを解読します。String
toString()
ルックアップの実行元となるクラスの名前を表示します。MethodHandle
unreflect(Method m)
ルックアップ・クラスがアクセス権を持つ場合に、mへの直接メソッド・ハンドルを作成します。MethodHandle
unreflectConstructor(Constructor<?> c)
リフレクトされたコンストラクタのメソッド・ハンドルを生成します。MethodHandle
unreflectGetter(Field f)
リフレクトされたフィールドに対する読取りアクセスを提供するメソッド・ハンドルを生成します。MethodHandle
unreflectSetter(Field f)
リフレクトされたフィールドに対する書込みアクセスを提供するメソッド・ハンドルを生成します。MethodHandle
unreflectSpecial(Method m, Class<?> specialCaller)
リフレクトされたメソッドのメソッド・ハンドルを生成します。VarHandle
unreflectVarHandle(Field f)
クラスR
で宣言されたT
型の反映されたフィールドf
へのアクセスを提供するVarHandleを生成します。
-
-
-
フィールドの詳細
-
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
-
-