- java.lang.Object
-
- java.lang.invoke.MethodHandles.Lookup
-
- Enclosing class:
- MethodHandles
public static final class MethodHandles.Lookup extends Object
查找对象是用于在创建需要访问检查时创建方法句柄的工厂。 方法句柄在调用它们时不执行访问检查,而是在创建它们时执行。 因此,在创建方法句柄时必须强制执行方法句柄访问限制。 强制执行这些限制的调用者类称为lookup class 。需要创建方法句柄的查找类将调用
MethodHandles.lookup
为自己创建工厂。 创建Lookup
工厂对象时,将确定查找类的标识,并将其安全地存储在Lookup
对象中。 然后,查找类(或其委托)可以使用Lookup
对象上的工厂方法为访问检查的成员创建方法句柄。 这包括允许查找类的所有方法,构造函数和字段,甚至是私有的。查找工厂方法
Lookup
对象上的工厂方法对应于方法,构造函数和字段的所有主要用例。 工厂方法创建的每个方法句柄都是特定字节码行为的功能等价物。 (字节码行为在Java虚拟机规范的5.4.3.5节中描述。)以下是这些工厂方法与生成的方法句柄行为之间的对应关系的摘要: lookup method behaviors lookup expression member bytecode behaviorlookup.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
表示空引用,否则表示this
。 名称aMethod
,aField
,和aConstructor
代表对应于给定构件反射的对象。findClass
操作的字节码行为是常量类的加载,就像ldc CONSTANT_Class
。 表示的行为不是作为方法句柄,而是直接表示为类
常量。在给定成员具有可变arity(即,方法或构造函数)的情况下,返回的方法句柄也将是variable arity 。 在所有其他情况下,返回的方法句柄将是固定的。
讨论:查找方法句柄与底层类成员和字节码行为之间的等价可以通过以下几种方式分解:
- 如果
C
无法从查找类的加载器以符号形式访问,则查找仍然可以成功,即使没有等效的Java表达式或字节编码常量也是如此。 - 同样,如果
T
或MT
无法从查找类的加载器以符号方式访问,则查找仍然可以成功。 例如,无论请求的类型如何,查找MethodHandle.invokeExact
和MethodHandle.invoke
将始终成功。 - 如果安装了安全管理器,则可以基于各种理由禁止查找( see below )。 相反,
CONSTANT_MethodHandle
常量上的ldc
指令不受安全管理器检查的约束。 - 如果查找方法具有very large arity ,则方法句柄创建可能会失败,因为方法句柄类型具有太多参数。
访问检查
创建方法句柄时,将在Lookup
的工厂方法中应用访问检查。 这是与Core Reflection API的主要区别,因为java.lang.reflect.Method.invoke
会在每次调用时对每个调用者执行访问检查。所有访问检查都从
Lookup
对象开始,该对象将其记录的查找类与创建方法句柄的所有请求进行比较。 单个Lookup
对象可用于创建任意数量的访问检查方法句柄,所有这些句柄都针对单个查找类进行检查。Lookup
对象可以与其他可信代码共享,例如元对象协议。 共享Lookup
对象委托在查找类的私有成员上创建方法句柄的功能。 即使特权代码使用Lookup
对象,访问检查也仅限于原始查找类的特权。查找可能会失败,因为查找类无法访问包含类,或者因为缺少所需的类成员,或者因为查找类无法访问所需的类成员,或者因为查找对象不够信任访问该成员。 在任何这些情况下,将尝试查找抛出
ReflectiveOperationException
。 确切的类将是以下之一:- NoSuchMethodException - 如果请求方法但不存在
- NoSuchFieldException - 如果请求字段但不存在
- IllegalAccessException - 如果成员存在但访问检查失败
通常,可以为方法
M
查找方法句柄的条件不比查找类可以编译,验证和解析对M
的调用的条件更具限制性。 在JVM引发异常(如NoSuchMethodError
,方法句柄查找通常会引发相应的已检查异常,例如NoSuchMethodException
。 并调用从查询产生的方法处理的效果是exactly equivalent ,以执行编制,验证和解决呼叫M
。 字段和构造函数也是如此。讨论:访问检查仅适用于命名和反射的方法,构造函数和字段。 其他方法句柄创建方法(如
MethodHandle.asType
)不需要任何访问检查,并且独立于任何Lookup
对象使用。如果所需成员是
protected
,则应用通常的JVM规则,包括要求查找类必须与所需成员位于同一包中,或者必须继承该成员。 (请参阅Java虚拟机规范,第4.9.2,5.4.3.5和6.4节。)此外,如果所需成员是不同包中的非静态字段或方法,则生成的方法句柄可能仅适用于查找类的对象或其子类之一。 通过将前导this
参数的类型从C
(必须是查找类的超类)缩小到查找类本身来强制执行此要求。JVM对
invokespecial
指令施加了类似的要求,即receiver参数必须与已解析的方法和当前类匹配。 同样,通过将前导参数的类型缩小到结果方法句柄来强制执行此要求。 (请参阅Java虚拟机规范,第4.10.1.9节。)JVM将构造函数和静态初始化程序块表示为具有特殊名称的内部方法(
"<init>"
和"<clinit>"
)。 调用指令的内部语法允许它们引用这些内部方法,就好像它们是普通方法一样,但JVM字节码验证器拒绝它们。 查找这样的内部方法将产生NoSuchMethodException
。如果嵌套类型之间的关系直接通过
NestHost
和NestMembers
属性表示(请参阅Java虚拟机规范,第4.7.28和4.7.29节),则关联的Lookup
对象提供对查找类及其所有嵌套类的直接访问(见Class.getNestHost
)。 否则,Java编译器会创建一个包装器方法来访问同一个嵌套中另一个类的私有方法,从而获得嵌套类之间的访问。 例如,一个嵌套类C.D
可以其他相关的类如内访问私有成员C
,C.D.E
,或C.B
,但是Java编译器可能需要生成在这些相关的类包装方法。 在这种情况下,一个Lookup
的对象C.E
将无法访问这些私有成员。 此限制的解决方法是Lookup.in
方法,该方法可以将C.E
上的查找C.E
为任何其他类上的查找,而无需特殊的特权提升。允许给定查找对象的访问可以根据其
lookupModes
的集合限制为通常可由查找类访问的成员的子集。 例如,publicLookup
方法生成一个查找对象,该对象仅允许访问导出包的公共类中的公共成员。 调用者敏感方法lookup
产生具有相对于其调用者类的全部能力的查找对象,以模拟所有支持的字节码行为。 此外,Lookup.in
方法可以生成具有比原始查找对象更少的访问模式的查找对象。关于 私人访问的 讨论:如果查询包含访问
private
成员(包括巢友的私人成员)的可能性,我们说查找具有私人访问权限 。 如其他地方的相关方法所述,只有具有私有访问权限的查找才具有以下功能:- 访问查找类及其nestmates的私有字段,方法和构造函数
- create方法句柄,用于调用caller sensitive方法,例如
Class.forName
- create方法句柄有哪些
emulate invokespecial
指令 - 对于查找类可访问的类,请避免使用package access checks
- 创建
delegated lookup objects
,它可以私有访问同一个包成员中的其他类
这些权限中的每一个都是这样一个事实的结果:具有私有访问权限的查找对象可以安全地追溯到原始类,其bytecode behaviors和Java语言访问权限可以通过方法句柄可靠地确定和模拟。
安全管理器交互
尽管字节码指令只能引用相关类加载器中的类,但只要对其类
对象的引用可用,此API就可以在任何类中搜索方法。 使用Core Reflection API也可以使用这种交叉加载器引用,并且不可能对诸如invokestatic
或getfield
指令进行字节getfield
。 有一个security manager API允许应用程序检查此类交叉加载器引用。 这些检查适用于MethodHandles.Lookup
API和Core Reflection API(如类
中所示 )。如果存在安全管理器,则成员和类查找将受到额外检查。 从一到三次调用安全管理器。 任何这些调用都可以通过抛出
SecurityException
来拒绝访问。 将smgr
定义为安全管理器,将lookc
定义为当前查找对象的查找类,将refc
为要在其中查找成员的包含类,将defc
定义为实际定义该成员的类。 (如果一个类或其他类型的被存取时,refc
个defc
值是类本身。)的值lookc
被定义为不存在 ,如果当前查找对象不具有private access 。 呼叫根据以下规则进行:- 步骤1:如果
lookc
不存在,或者如果它的类加载器是不一样的或的类加载器的祖先refc
,然后smgr.checkPackageAccess(refcPkg)
被调用,其中refcPkg
是的包refc
。 - 步骤2a:如果检索到的成员不是公共的并且
lookc
不存在,则调用smgr.checkPermission
和RuntimePermission("accessDeclaredMembers")
。 - 步骤2b:如果检索到的类具有
null
类加载器,并且lookc
不存在,则调用smgr.checkPermission
和RuntimePermission("getClassLoader")
。 - 步骤3:如果所检索的部件是不公开的,而如果
lookc
不存在,并且如果defc
和refc
不同,则smgr.checkPackageAccess(defcPkg)
被调用,其中defcPkg
是的包defc
。
来电者敏感的方法
少数Java方法具有称为调用者敏感性的特殊属性。 调用者敏感方法的行为可能会有所不同,具体取决于其直接调用者的身份。如果请求了调用者敏感方法的方法句柄,则适用bytecode behaviors的一般规则,但它们以特殊方式考虑查找类。 生成的方法句柄的行为就像从查找类中包含的指令调用一样,以便调用者敏感的方法检测查找类。 (相比之下,方法句柄的调用者被忽略。)因此,在调用者敏感方法的情况下,不同的查找类可能会产生不同行为的方法句柄。
如果查找对象是
publicLookup()
,或者没有private access的其他查找对象,则忽略查找类。 在这种情况下,不能创建调用者敏感的方法句柄,禁止访问,并且查找失败,并显示IllegalAccessException
。讨论:例如,调用者敏感方法
Class.forName(x)
可以返回不同的类或抛出不同的异常,具体取决于调用它的类的类加载器。Class.forName
的公共查找将失败,因为没有合理的方法来确定其字节码行为。如果应用程序缓存方法句柄以进行广泛共享,则应使用
publicLookup()
来创建它们。 如果查找Class.forName
,它将失败,并且应用程序必须采取适当的操作。 可能是稍后的查找(可能在调用引导方法期间)可以包含调用者的特定标识,从而使该方法可访问。函数
MethodHandles.lookup
调用者敏感,因此可以为查找提供安全的基础。 JSR 292 API中几乎所有其他方法都依赖于查找对象来检查访问请求。
-
-
字段汇总
字段 变量和类型 字段 描述 static int
模块
表示模块
访问(默认访问)的单位掩码,可能会导致lookupModes
的结果。static int
PACKAGE
表示package
访问权限(默认访问权限)的单位掩码,可能会导致lookupModes
的结果。static int
PRIVATE
表示private
访问的单比特掩码,可能导致lookupModes
的结果。static int
PROTECTED
表示protected
访问的单位掩码,可能导致lookupModes
的结果。static int
PUBLIC
表示public
访问的单位掩码,可能导致lookupModes
的结果。static int
UNCONDITIONAL
表示unconditional
访问权限的单位掩码,可能导致lookupModes
的结果。
-
方法摘要
所有方法 实例方法 具体的方法 变量和类型 方法 描述 类<?>
accessClass(类<?> targetClass)
确定是否可以从此Lookup
对象定义的查找上下文中访问类。MethodHandle
bind(Object receiver, String name, MethodType type)
为非静态方法生成早期绑定方法句柄。类<?>
defineClass(byte[] bytes)
为同一个类加载器和相同的运行时包定义一个类,并将protection domain定义为此查找的lookup class 。MethodHandles.Lookup
dropLookupMode(int modeToDrop)
在查找对象找到成员的同一查找类上创建查找,但查找模式已丢失给定的查找模式。类<?>
findClass(String targetName)
从此Lookup
对象定义的查找上下文中按名称查找类。MethodHandle
findConstructor(类<?> refc, MethodType type)
生成一个方法句柄,该句柄使用指定类型的构造函数创建对象并对其进行初始化。MethodHandle
findGetter(类<?> refc, String name, 类<?> type)
生成一个方法句柄,提供对非静态字段的读访问权限。MethodHandle
findSetter(类<?> refc, String name, 类<?> type)
生成一个方法句柄,提供对非静态字段的写访问权限。MethodHandle
findSpecial(类<?> refc, String name, MethodType type, 类<?> specialCaller)
为虚方法生成早期绑定方法句柄。MethodHandle
findStatic(类<?> refc, String name, MethodType type)
生成静态方法的方法句柄。MethodHandle
findStaticGetter(类<?> refc, String name, 类<?> type)
生成一个方法句柄,提供对静态字段的读访问权限。MethodHandle
findStaticSetter(类<?> refc, String name, 类<?> type)
生成一个方法句柄,提供对静态字段的写访问权限。VarHandle
findStaticVarHandle(类<?> decl, String name, 类<?> type)
产生VarHandle给访问静态字段name
类型type
在类类型的声明decl
。VarHandle
findVarHandle(类<?> recv, String name, 类<?> type)
生成一个VarHandle,允许访问类型为name
的类型为type
的类型为recv
。MethodHandle
findVirtual(类<?> refc, String name, MethodType type)
生成虚方法的方法句柄。boolean
hasPrivateAccess()
如果此查找具有PRIVATE
访问权限,则返回true
。MethodHandles.Lookup
in(类<?> requestedLookupClass)
在指定的新查找类上创建查找。类<?>
lookupClass()
告诉哪个类正在执行查找。int
lookupModes()
告知此查找对象可以生成哪些成员访问保护类。MethodHandleInfo
revealDirect(MethodHandle target)
破解由此查找对象或类似对象创建的 direct method handle 。String
toString()
显示要从中进行查找的类的名称。MethodHandle
unreflect(方法 m)
如果查找类具有权限,则将 direct method handle设置为 m 。MethodHandle
unreflectConstructor(构造器<?> c)
为反射的构造函数生成方法句柄。MethodHandle
unreflectGetter(字段 f)
生成一个方法句柄,提供对反射字段的读访问权限。MethodHandle
unreflectSetter(字段 f)
生成一个方法句柄,提供对反射字段的写访问权限。MethodHandle
unreflectSpecial(方法 m, 类<?> specialCaller)
为反射方法生成方法句柄。VarHandle
unreflectVarHandle(字段 f)
生成一个VarHandle,允许访问类型为f
的类型为T
的类型为R
。
-
-
-
字段详细信息
-
PUBLIC
public static final int PUBLIC
表示public
访问的单位掩码,可能导致lookupModes
的结果。 值0x01
恰好与public
modifier bit的值相同。- 另请参见:
- 常数字段值
-
PRIVATE
public static final int PRIVATE
代表private
访问的单位掩码,可能导致lookupModes
的结果。 值0x02
恰好与private
modifier bit的值相同。- 另请参见:
- 常数字段值
-
PROTECTED
public static final int PROTECTED
表示protected
访问的单位掩码,可能有助于lookupModes
的结果。 值0x04
恰好与protected
modifier bit的值相同。- 另请参见:
- 常数字段值
-
PACKAGE
public static final int PACKAGE
表示package
访问(默认访问)的单位掩码,可能会导致lookupModes
的结果。 值为0x08
,与任何特定的modifier bit无意义地对应。- 另请参见:
- 常数字段值
-
模块
public static final int MODULE
表示模块
访问(默认访问)的单位掩码,可能会导致lookupModes
的结果。 值为0x10
,与任何特定的modifier bit无意义地对应。 与PUBLIC
修饰符位一起使用具有此查找模式的Lookup
可以访问查找类模块中的所有公共类型以及其他模块导出到查找类模块的包中的公共类型。- 从以下版本开始:
- 9
- 另请参见:
- 常数字段值
-
UNCONDITIONAL
public static final int UNCONDITIONAL
表示unconditional
访问权限的单位掩码,可能导致lookupModes
的结果。 值为0x20
,与任何特定的modifier bit无意义地对应。 一个Lookup
这种查找模式取得readability 。 与PUBLIC
修饰符位一起使用具有此查找模式的Lookup
可以访问所有模块的公共类型的所有公共成员,其中类型位于包exported unconditionally
中 。- 从以下版本开始:
- 9
- 另请参见:
-
MethodHandles.publicLookup()
, 常数字段值
-
-
方法详细信息
-
lookupClass
public 类<?> lookupClass()
- 结果
- 查找类,代表该查找对象查找成员
-
lookupModes
public int lookupModes()
告知此查找对象可以生成哪些成员访问保护类。 结果是比特的位掩码PUBLIC (0x01) , PRIVATE (0x02) , PROTECTED (0x04) , PACKAGE (0x08) , MODULE (0x10) ,和UNCONDITIONAL (0x20) 。caller's class上新创建的查找对象具有所有可能的位设置,但
UNCONDITIONAL
除外。 新查找类created from a previous lookup object上的查找对象可能将某些模式位设置为零。 模式位也可以是directly cleared 。 清除后,无法从降级的查找对象恢复模式位。 这样做的目的是通过新的查找对象限制访问,以便它只能访问原始查找对象可以访问的名称,也可以访问新的查找类。- 结果
- 查找模式,限制此查找对象执行的访问类型
- 另请参见:
-
in(java.lang.Class<?>)
,dropLookupMode(int)
-
in
public MethodHandles.Lookup in(类<?> requestedLookupClass)
在指定的新查找类上创建查找。 生成的对象将报告指定的类为其自己的lookupClass
。但是,保证生成的
Lookup
对象不再具有Lookup
对象的访问权限。 特别是,访问功能可能会丢失如下:- 如果旧查找类位于
named
模块中,并且新查找类位于不同的模块M
,则无法访问成员,甚至M
的导出包中的公共成员。 例外情况是此查找为publicLookup
,在这种情况下,PUBLIC
访问不会丢失。 - 如果旧的查找类位于未命名的模块中,并且新的查找类是不同的模块,则会丢失
模块
访问权限。 - 如果新查找类与旧查找类不同,则丢失
UNCONDITIONAL
。 - 如果新查找类与旧查找类不同,则无法访问受保护和默认(包)成员。
- 如果新查找类与旧查找类不在同一个包成员中,则不能访问私有成员,并且凭借继承将无法访问受保护的成员。 (由于包共享,受保护的成员可能继续可访问。)
- 如果旧查找类无法访问新的查找类,则无法访问任何成员,甚至是公共成员。 (在所有其他情况下,公共成员将继续可访问。)
生成的查找加载类的功能(在
findClass(java.lang.String)
调用期间使用)由查找类'加载程序确定,加载程序可能会因此操作而更改。- 参数
-
requestedLookupClass
- 新查找对象的所需查找类 - 结果
- 报告所需查找类的查找对象,如果没有更改则报告相同的对象
- 异常
-
NullPointerException
- 如果参数为null
- 如果旧查找类位于
-
dropLookupMode
public MethodHandles.Lookup dropLookupMode(int modeToDrop)
在查找对象找到成员的同一查找类上创建查找,但查找模式已丢失给定的查找模式。 查找模式下降是一个PUBLIC
,模块
,PACKAGE
,PROTECTED
或PRIVATE
。PROTECTED
和UNCONDITIONAL
始终被删除,因此生成的查找模式将永远不会具有这些访问功能。 删除PACKAGE
,生成的查找将不具有PACKAGE
或PRIVATE
访问权限。 当拖放模块
然后将得到的查找不会有模块
,PACKAGE
,或PRIVATE
访问。 如果PUBLIC
,则生成的查找无权访问。- 参数
-
modeToDrop
- 要删除的查找模式 - 结果
- 缺少指示模式的查找对象,如果没有更改,则返回相同的对象
- 异常
-
IllegalArgumentException
-如果modeToDrop
不是一个PUBLIC
,模块
,PACKAGE
,PROTECTED
,PRIVATE
或UNCONDITIONAL
- 从以下版本开始:
- 9
- 另请参见:
-
MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
-
defineClass
public 类<?> defineClass(byte[] bytes) throws IllegalAccessException
为同一个类加载器和相同的运行时包定义一个类,并将protection domain定义为此查找的lookup class 。此查找的lookup modes必须包含
PACKAGE
访问权限,因为该类可以访问默认(包)成员。PACKAGE
查找模式用于验证查找对象是由运行时包中的调用者创建的(或者是从最初由适当特权代码创建的查找派生到运行时包中的目标类)。bytes
参数是有效类文件的类字节(由Java虚拟机规范定义),其类名与查找类位于同一包中。此方法不运行类初始值设定项。 类初始化程序可以在以后运行,详见“Java语言规范”的第12.4节。
如果有安全管理器,则首先调用其
checkPermission
方法以检查RuntimePermission("defineClass")
。- 参数
-
bytes
- 类字节 - 结果
-
类
对象 - 异常
-
IllegalArgumentException
- 字节用于查找类的不同包中的类 -
IllegalAccessException
- 如果此查找没有PACKAGE
访问权限 -
LinkageError
- 如果类格式错误(ClassFormatError
),无法验证(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”。
- 如果仅允许公共,模块,包和私有访问,则后缀为“/ private”。
MethodHandles.lookup
获得的对象。 由Lookup.in
创建的对象始终具有受限访问权限,并将显示后缀。(受保护的访问应该比私有访问更强大可能看起来很奇怪。独立于包访问,受保护的访问首先被丢失,因为它需要调用者和被调用者之间的直接子类关系。)
- 重写:
-
toString
在类Object
- 结果
- 对象的字符串表示形式。
- 另请参见:
-
in(java.lang.Class<?>)
-
findStatic
public MethodHandle findStatic(类<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
生成静态方法的方法句柄。 方法句柄的类型将是方法的类型。 (由于静态方法不接收接收器,因此没有额外的接收器参数插入到方法句柄类型中,就像findVirtual
或findSpecial
一样 。)查找对象必须可以访问该方法及其所有参数类型。当且仅当设置了方法的变量arity修饰符位(
0x0080
)时,返回的方法句柄才会有variable arity 。如果调用返回的方法句柄,则初始化方法的类(如果尚未初始化)。
例:
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
,或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null
-
findVirtual
public MethodHandle findVirtual(类<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
生成虚方法的方法句柄。 方法句柄的类型将是方法的类型,前缀为接收器类型(通常为refc
)。 查找对象必须可以访问该方法及其所有参数类型。调用时,句柄将第一个参数视为接收者,对于非私有方法,调度接收者的类型以确定要输入的方法实现。 对于私有方法,将在接收器上调用
refc
的命名方法。 (调度操作与invokevirtual
或invokeinterface
指令执行的操作相同。)如果查找类具有访问该成员的完全权限,则第一个参数的类型为
refc
。 否则,该成员必须为protected
并且第一个参数的类型将限制为查找类。当且仅当设置了方法的变量arity修饰符位(
0x0080
)时,返回的方法句柄将具有variable arity 。因为一般equivalence之间
invokevirtual
的指令和方法所生产手柄findVirtual
,如果类是MethodHandle
和名称的字符串是invokeExact
或invoke
,所得方法手柄等效于一个由产生MethodHandles.exactInvoker
或MethodHandles.invoker
具有相同type
参数。如果类为
VarHandle
且名称字符串对应于签名多态访问模式方法的名称,则生成的方法句柄等效于MethodHandles.varHandleInvoker(java.lang.invoke.VarHandle.AccessMode, java.lang.invoke.MethodType)
生成的方法句柄,其访问模式对应于名称字符串且具有相同的type
参数。例:
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
- 方法的类型,省略receiver参数 - 结果
- 所需的方法句柄
- 异常
-
NoSuchMethodException
- 如果该方法不存在 -
IllegalAccessException
- 如果访问检查失败,或者方法是static
,或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null
-
findConstructor
public MethodHandle findConstructor(类<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException
生成一个方法句柄,该句柄使用指定类型的构造函数创建对象并对其进行初始化。 方法句柄的参数类型将是构造函数的参数类型,而返回类型将是对构造函数类的引用。 查找对象必须可以访问构造函数及其所有参数类型。请求的类型必须具有返回类型
void
。 (这与JVM对构造函数类型描述符的处理一致。)当且仅当构造函数的变量arity修饰符位(
0x0080
)已设置时,返回的方法句柄才会有variable arity 。如果调用返回的方法句柄,则初始化构造函数的类(如果尚未初始化)。
例:
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
- 方法的类型,省略了receiver参数,以及void返回类型 - 结果
- 所需的方法句柄
- 异常
-
NoSuchMethodException
- 如果构造函数不存在 -
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null
-
findClass
public 类<?> findClass(String targetName) throws ClassNotFoundException, IllegalAccessException
从此Lookup
对象定义的查找上下文中按名称查找类。 该类的静态初始值设定项未运行。此处的查找上下文由lookup class及其类加载器和lookup modes确定 。 特别是,该方法首先尝试加载所请求的类,然后确定该查找对象是否可以访问该类。
- 参数
-
targetName
- 要查找的类的完全限定名称。 - 结果
- 要求的课程。
- 异常
-
SecurityException
- 如果存在安全管理器且 refuses access -
LinkageError
- 如果链接失败 -
ClassNotFoundException
- 如果查找类的加载程序无法加载该类。 -
IllegalAccessException
- 如果无法访问该类,则使用允许的访问模式。 -
SecurityException
- 如果存在安全管理器且 refuses access - 从以下版本开始:
- 9
-
accessClass
public 类<?> accessClass(类<?> targetClass) throws IllegalAccessException
- 参数
-
targetClass
- 要访问检查的类 - 结果
- 已访问检查的类
- 异常
-
IllegalAccessException
- 如果无法使用允许的访问模式从查找类访问该类。 -
SecurityException
- 如果存在安全管理器且 refuses access - 从以下版本开始:
- 9
-
findSpecial
public MethodHandle findSpecial(类<?> refc, String name, MethodType type, 类<?> specialCaller) throws NoSuchMethodException, IllegalAccessException
为虚方法生成早期绑定方法句柄。 它会绕过检查重写在接收机,方法as if called从invokespecial
从明确内指令指定specialCaller
。 方法句柄的类型将是方法的类型,具有适当受限的接收器类型。 (接收器类型将为specialCaller
或子类型。)查找对象必须可以访问该方法及其所有参数类型。在方法解析之前,如果显式指定的调用者类与查找类不相同,或者此查找对象没有private access特权,则访问将失败。
当且仅当设置了方法的变量arity修饰符位(
0x0080
)时,返回的方法句柄将具有variable arity 。(注意:此API不显示名为
"<init>"
JVM内部方法,即使invokespecial
指令在特殊情况下可以引用它们。使用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
- 方法的类型,省略receiver参数 -
specialCaller
- 建议的调用类执行invokespecial
- 结果
- 所需的方法句柄
- 异常
-
NoSuchMethodException
- 如果该方法不存在 -
IllegalAccessException
- 如果访问检查失败,或者方法是static
,或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null
-
findGetter
public MethodHandle findGetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
生成一个方法句柄,提供对非静态字段的读访问权限。 方法句柄的类型将具有字段值类型的返回类型。 方法句柄的单个参数将是包含该字段的实例。 代表查找类立即执行访问检查。- 参数
-
refc
- 从中访问方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个方法句柄,可以从字段加载值
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者字段为static
-
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null - 另请参见:
-
findVarHandle(Class, String, Class)
-
findSetter
public MethodHandle findSetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
生成一个方法句柄,提供对非静态字段的写访问权限。 方法句柄的类型将具有void返回类型。 方法句柄将采用两个参数,包含字段的实例和要存储的值。 第二个参数将是字段的值类型。 代表查找类立即执行访问检查。- 参数
-
refc
- 从中访问方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个方法句柄,可以将值存储到字段中
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者字段为static
-
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null - 另请参见:
-
findVarHandle(Class, String, Class)
-
findVarHandle
public VarHandle findVarHandle(类<?> recv, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
生成VarHandle,允许访问类型为name
的类型为type
的非静态字段recv
。 VarHandle的变量类型是type
,它有一个坐标类型,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 Note:
-
由数值和原子更新访问模式执行的
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
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null - 从以下版本开始:
- 9
- 如果声明字段为
-
findStaticGetter
public MethodHandle findStaticGetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
生成一个方法句柄,提供对静态字段的读访问权限。 方法句柄的类型将具有字段值类型的返回类型。 方法句柄不带参数。 代表查找类立即执行访问检查。如果调用返回的方法句柄,则初始化字段的类(如果尚未初始化)。
- 参数
-
refc
- 从中访问方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个方法句柄,可以从字段加载值
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段不是static
-
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null
-
findStaticSetter
public MethodHandle findStaticSetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
生成一个方法句柄,提供对静态字段的写访问权限。 方法句柄的类型将具有void返回类型。 方法句柄将采用字段值类型的单个参数,即要存储的值。 代表查找类立即执行访问检查。如果调用返回的方法句柄,则初始化字段的类(如果尚未初始化)。
- 参数
-
refc
- 从中访问方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个方法句柄,可以将值存储到字段中
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段不是static
-
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null
-
findStaticVarHandle
public VarHandle findStaticVarHandle(类<?> decl, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
生成一个VarHandle,允许访问类型为name
的类型为type
的静态字段decl
。 VarHandle的变量类型是type
,它没有坐标类型。代表查找类立即执行访问检查。
如果操作返回的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 Note:
-
由数值和原子更新访问模式执行的
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
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null - 从以下版本开始:
- 9
- 如果该字段声明为
-
bind
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
为非静态方法生成早期绑定方法句柄。 接收方必须具有超类型defc
,其中查找类可以访问给定名称和类型的方法。 查找对象必须可以访问该方法及其所有参数类型。 方法句柄的类型将是方法的类型,而不插入任何额外的接收器参数。 给定的接收器将绑定到方法句柄中,以便对方法句柄的每次调用都将在给定的接收器上调用所请求的方法。当且仅当方法的变量arity修饰符位(
0x0080
)已设置且尾随数组参数不是唯一参数时,返回的方法句柄将具有variable arity 。 (如果尾随数组参数是唯一的参数,则给定的接收器值将绑定到它。)这几乎等同于以下代码,下面提到了一些差异:
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()
或receiver.getClass()
的超类型,其中查找类可以访问所请求的方法。 (与bind
不同,bindTo
不保留变量arity。另外,bindTo
可能会抛出ClassCastException
,其中bind
会抛出IllegalAccessException
,如成员为protected
并且接收器被findVirtual
限制为查找类。)- 参数
-
receiver
- 从中访问方法的对象 -
name
- 方法的名称 -
type
- 方法的类型,省略receiver参数 - 结果
- 所需的方法句柄
- 异常
-
NoSuchMethodException
- 如果该方法不存在 -
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
SecurityException
- 如果存在安全管理器且 refuses access -
NullPointerException
- 如果任何参数为null - 另请参见:
-
MethodHandle.bindTo(java.lang.Object)
,findVirtual(java.lang.Class<?>, java.lang.String, java.lang.invoke.MethodType)
-
unreflect
public MethodHandle unreflect(方法 m) throws IllegalAccessException
如果查找类具有权限,则将direct method handle设置为m 。 如果m是非静态的,则将receiver参数视为初始参数。 如果m是虚拟的,则在每次调用时都会遵守覆盖。 与Core Reflection API不同, 不包含异常。 方法句柄的类型将是方法的类型,接收器类型前置(但仅当它是非静态的)。 如果未设置方法的accessible
标志,则代表查找类立即执行访问检查。 如果m不公开,请不要与不受信任的方共享生成的句柄。当且仅当设置了方法的变量arity修饰符位(
0x0080
)时,返回的方法句柄将具有variable arity 。如果m是静态的,并且如果调用返回的方法句柄,则初始化方法的类(如果尚未初始化)。
- 参数
-
m
- 反映的方法 - 结果
- 一个方法句柄,可以调用反射的方法
- 异常
-
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
NullPointerException
- 如果参数为null
-
unreflectSpecial
public MethodHandle unreflectSpecial(方法 m, 类<?> specialCaller) throws IllegalAccessException
为反射方法生成方法句柄。 它会绕过检查重写在接收机,方法as if called从invokespecial
从明确内指令指定specialCaller
。 方法句柄的类型将是方法的类型,具有适当受限的接收器类型。 (接收器类型将为specialCaller
或子类型。)如果未设置方法的accessible
标志,则代表查找类立即执行访问检查,就像链接了invokespecial
指令一样。在方法解析之前,如果显式指定的调用者类与查找类不相同,或者此查找对象没有private access特权,则访问将失败。
当且仅当设置了方法的变量arity修饰符位(
0x0080
)时,返回的方法句柄将具有variable arity 。- 参数
-
m
- 反映的方法 -
specialCaller
- 名义上调用该方法的类 - 结果
- 一个方法句柄,可以调用反射的方法
- 异常
-
IllegalAccessException
- 如果访问检查失败,或者方法是static
,或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
NullPointerException
- 如果任何参数为null
-
unreflectConstructor
public MethodHandle unreflectConstructor(构造器<?> c) throws IllegalAccessException
为反射的构造函数生成方法句柄。 方法句柄的类型将是构造函数的类型,返回类型更改为声明类。 方法句柄将执行newInstance
操作,在传递给方法句柄的参数上创建构造函数类的新实例。如果未设置构造函数的
accessible
标志,则代表查找类立即执行访问检查。当且仅当设置了构造函数的变量arity修饰符位(
0x0080
)时,返回的方法句柄才会有variable arity 。如果调用返回的方法句柄,则初始化构造函数的类(如果尚未初始化)。
- 参数
-
c
- 反射的构造函数 - 结果
- 一个方法句柄,可以调用反射的构造函数
- 异常
-
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位已设置且asVarargsCollector
失败 -
NullPointerException
- 如果参数为null
-
unreflectGetter
public MethodHandle unreflectGetter(字段 f) throws IllegalAccessException
生成一个方法句柄,提供对反射字段的读访问权限。 方法句柄的类型将具有字段值类型的返回类型。 如果该字段是静态的,则方法句柄不带参数。 否则,它的单个参数将是包含该字段的实例。 如果未设置字段的accessible
标志,则代表查找类立即执行访问检查。如果该字段是静态的,并且如果调用返回的方法句柄,则将初始化该字段的类(如果尚未初始化)。
- 参数
-
f
- 反射场 - 结果
- 方法句柄,可以从反射字段加载值
- 异常
-
IllegalAccessException
- 如果访问检查失败 -
NullPointerException
- 如果参数为null
-
unreflectSetter
public MethodHandle unreflectSetter(字段 f) throws IllegalAccessException
生成一个方法句柄,提供对反射字段的写访问权限。 方法句柄的类型将具有void返回类型。 如果该字段是静态的,则方法句柄将采用字段值类型的单个参数,即要存储的值。 否则,这两个参数将是包含该字段的实例,以及要存储的值。 如果未设置字段的accessible
标志,则代表查找类立即执行访问检查。如果该字段是静态的,并且如果调用返回的方法句柄,则将初始化该字段的类(如果尚未初始化)。
- 参数
-
f
- 反射场 - 结果
- 方法句柄,可以将值存储到反射字段中
- 异常
-
IllegalAccessException
- 如果访问检查失败 -
NullPointerException
- 如果参数为null
-
unreflectVarHandle
public VarHandle unreflectVarHandle(字段 f) throws IllegalAccessException
生成一个VarHandle,允许访问类型为T
的一个f
类型的反射字段R
。 VarHandle的变量类型是T
。 如果该字段是非静态的,则VarHandle具有一个坐标类型,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 Note:
-
由数值和原子更新访问模式执行的
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)
破解由此查找对象或类似对象创建的direct method handle 。 执行安全性和访问检查以确保该查找对象能够再现目标方法句柄。 这意味着如果target是直接方法句柄但是由不相关的查找对象创建,则破解可能会失败。 如果方法句柄是caller sensitive并且由另一个类的查找对象创建,则会发生这种情况。- 参数
-
target
- 破解为符号引用组件的直接方法句柄 - 结果
- 一个符号引用,可用于从此查找对象重建此方法句柄
- 异常
-
SecurityException
- 如果存在安全管理器且 refuses access -
IllegalArgumentException
- 如果目标不是直接方法句柄或访问检查失败 -
NullPointerException
- 如果目标是null
- 从以下版本开始:
- 1.8
- 另请参见:
-
MethodHandleInfo
-
hasPrivateAccess
public boolean hasPrivateAccess()
如果此查找具有PRIVATE
访问权限,则返回true
。- 结果
-
true
如果此查找具有PRIVATE
访问权限。 - 从以下版本开始:
- 9
-
-