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

クラスMethodHandles.Lookup

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

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

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

Lookupファクトリ・メソッド

Lookupオブジェクトのファクトリ・メソッドは、メソッド、コンストラクタ、およびフィールドのすべてのメジャーなユース・ケースに対応しています。 ファクトリ・メソッドによって作成される各メソッド・ハンドルは、特定のバイトコード動作と機能的に同等です。 (バイトコード動作は『Java Virtual Machine Specification』のセクション5.4.3.5に記述されています。) これらのファクトリ・メソッドと、結果として得られるメソッド・ハンドルの動作との対応のサマリーを以下に示します:
ルックアップ・メソッドの動作
ルックアップ式 メンバー バイトコード動作
lookup.findGetter(C.class,"f",FT.class) FT f;(T) this.f;
lookup.findStaticGetter(C.class,"f",FT.class) static
FT f;
(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という名前のパラメータとしてドキュメント化されています。 仮パラメータthisC型の自己参照を表しています。これは、存在する場合は常にメソッド・ハンドル呼出しの先頭の引数になります。 (一部のprotectedメンバーでは、thisの型がルックアップ・クラスに制限される場合があります。下記を参照してください。) 名前argは、メソッド・ハンドルのほかのすべての引数を表しています。 Core Reflection APIのコード例に含まれる名前thisOrNullは、アクセス対象のメソッドやフィールドがstaticの場合はnull参照を表し、それ以外の場合はthisを表します。 名前aMethodaField、およびaConstructorは、指定されたメンバーに対応するリフレクション・オブジェクトを表しています。

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

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

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

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

アクセス・チェック

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

バイト・コード命令は関連クラス・ローダー内のクラスしか参照できませんが、このAPIでは、Classオブジェクトへの参照が使用可能であるかぎり、任意のクラス内のメソッドを検索できます。 そのようなクロスローダー参照は、Core Reflection APIでも可能ですが、invokestaticgetfieldなどのバイト・コード命令では不可能です。 アプリケーション内でそのようなクロスローダー参照をチェックできるようにするためのセキュリティ・マネージャ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)が呼び出されます(refcPkgrefcのパッケージ)。
  • ステップ2a: 取り出されたメンバーが公開されておらず、lookcが存在しない場合は、RuntimePermission("accessDeclaredMembers")を含むsmgr.checkPermissionが呼び出されます。
  • ステップ2b: 取得したクラスにnullクラス・ローダーがあり、lookcが存在しない場合は、RuntimePermission("getClassLoader")を含むsmgr.checkPermissionが呼び出されます。
  • ステップ3: 取得されるメンバーがpublicでなく、lookcが存在せず、defcrefcが異なる場合は、smgr.checkPackageAccess(defcPkg)が呼び出されます(defcPkgdefcのパッケージ)。
セキュリティ・チェックは他のアクセス・チェックを合格した後に実行されます。 したがって、上記の規則は、パブリックであるメンバーまたはクラス、またはそのメンバーまたはクラスにアクセスするためのアクセス権を持つ参照クラスからアクセスされていることを前提としています。

呼出し元依存メソッド

少数の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​(クラス<?> 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​(クラス<?> 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を生成します。

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

    cloneequalsfinalizegetClasshashCodenotifynotifyAllwaitwaitwait
  • フィールド詳細

    • 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です。これは特定の「修飾子ビット」には意味がありません。 このルックアップ・モードのLookupreadabilityを想定しています。 PUBLIC修飾子ビットと組み合わせて、このルックアップ・モードを持つLookupは、型がパッケージ内のexported unconditionallyであるすべてのモジュールのパブリック型のすべてのパブリック・メンバーにアクセスできます。
      導入されたバージョン:
      9
      関連項目:
      MethodHandles.publicLookup(), 「定数フィールド値」
  • メソッドの詳細

    • lookupClass

      public クラス<?> 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​(クラス<?> 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)
      このルックアップ・オブジェクトがメンバーを検出するが、ルックアップ・モードでルックアップを作成して、ルックアップ・モードを失ったルックアップを作成します。 ドロップするルックアップ・モードは、PUBLICMODULEPACKAGEPROTECTEDまたはPRIVATEのいずれかです。 PROTECTEDUNCONDITIONALは常に削除されるため、結果のルックアップ・モードではこれらのアクセス機能は使用できません。 PACKAGEを削除すると、結果のルックアップにはPACKAGEまたはPRIVATEアクセスがありません。 MODULEをドロップすると、結果のルックアップにはMODULEPACKAGE、またはPRIVATEアクセスがありません。 PUBLICがドロップされた場合、結果のルックアップにはアクセス権がありません。
      パラメータ:
      modeToDrop - ルックアップ・モードをドロップ
      戻り値:
      示されたモードを持たない参照オブジェクト、または変更がなければ同じオブジェクト
      例外:
      IllegalArgumentException - modeToDropPUBLICMODULEPACKAGEPROTECTEDPRIVATEまたはUNCONDITIONALのいずれかでない場合
      導入されたバージョン:
      9
      関連項目:
      MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
    • defineClass

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

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

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

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

      セキュリティ・マネージャがある場合は、最初にcheckPermissionメソッドを呼び出してRuntimePermission("defineClass")をチェックします。

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

      public String toString()
      ルックアップの実行元となるクラスの名前を表示します。 (名前はClass.getNameから報告されるものです。) このルックアップに許可されるアクセスに制限がある場合、そのことを示すために、スラッシュとキーワードで構成される接尾辞がクラス名に追加されます。 キーワードは許可される最強のアクセスを表しており、次のように選択されます。
      • アクセスが一切許可されない場合、接尾辞は「/noaccess」になります。
      • エクスポートされたパッケージの型へのパブリック・アクセスのみが許可されている場合、サフィクスは"/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メソッドはレシーバを取らないため、findVirtualfindSpecialのように、メソッド・ハンドルの型に追加のレシーバ引数が挿入されることはありません。) このメソッドとそのすべての引数型にルックアップ・オブジェクトからアクセスできる必要があります。

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

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

      例:

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

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

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

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

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

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

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

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

      例:

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

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

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

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

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

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

      例:

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

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

      public Class<?> findClass​(String targetName) throws ClassNotFoundException, IllegalAccessException
      このLookupオブジェクトによって定義されたルックアップ・コンテキストからクラスを名前で検索します。 クラスの静的初期化子は実行されません。

      ここでのルックアップ・コンテキストは、「ルックアップ・クラス」、そのクラス・ローダー、および「ルックアップ・モード」によって決定されます。 具体的には、このメソッドは、最初にリクエストされたクラスをロードしようとし、そのクラスがこのルックアップ・オブジェクトにアクセス可能であるかどうかを判定します。

      パラメータ:
      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またはfinalである場合
      SecurityException - セキュリティ・マネージャが存在し、それがアクセスを拒否した場合
      NullPointerException - いずれかの引数がnullの場合
      関連項目:
      findVarHandle(Class, String, Class)
    • findVarHandle

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      public boolean hasPrivateAccess()
      このルックアップにPRIVATEアクセスがある場合は、trueを返します。
      戻り値:
      このルックアップにPRIVATEアクセスがある場合はtrue
      導入されたバージョン:
      9