在学习java9 StringConcatFactory
课程时,我无法理解为什么使用MethodHandles.publicLookup()
的代码会引发StringConcatException
异常,而如果使用MethodHandles.lookup()
则一切正常。
根据java docs of lookup:
“lookup - 表示具有辅助功能的查找上下文 来电者的特权“
StringConcatFactory.makeConcat(MethodHandles.publicLookup(),
"abc",MethodType.methodType(String.class));//Exception Here
StringConcatFactory.makeConcat(MethodHandles.lookup(),
"abc", MethodType.methodType(String.class)); //Working fine
我不确定我错在哪里?请帮助我理解这种行为。
答案 0 :(得分:6)
makeConcat
的javadoc说明了第一个参数:
查找表示具有调用者
的可访问权限的查找上下文
publicLookup
返回的查找上下文没有这些权限。
即使您没有连接任何内容,仍会抛出异常:
MethodType concatType = MethodType.methodType(String.class); // No arguments, returns String
StringConcatFactory.makeConcat(MethodHandles.publicLookup(), "abc", concatType); // Exception
因为在StringConcatFactory#doStringConcat
:
if ((lookup.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
throw new StringConcatException("Invalid caller: " +
lookup.lookupClass().getName());
}
上下文需要私有查找模式,publicLookup
没有它:
System.out.println((MethodHandles.publicLookup().lookupModes()
& MethodHandles.Lookup.PRIVATE) != 0); // false
System.out.println((MethodHandles.lookup().lookupModes()
& MethodHandles.Lookup.PRIVATE) != 0); // true
答案 1 :(得分:5)
publicLookup()
的Javadoc说:
返回受信任最低的查找对象。
与lookup():
返回具有完整功能的查找对象,以模拟调用者的所有支持的字节码行为。这些功能包括对呼叫者的私人访问。查找对象上的工厂方法可以为调用者通过字节码访问的任何成员创建直接方法句柄,包括受保护和私有字段和方法。此查找对象是可以委派给可信代理的功能。
makeConcat()
的Javadoc最后说:
throws StringConcatException - 如果违反了此处描述的任何链接不变量。
鉴于问题确实不包含更多细节,最可能的答案是:您在此处遇到某种“许可”问题。也许你试图“连接”在使用“最小信任”时根本不可用的东西。
答案 2 :(得分:3)
publicLookup
:
StringConcatFactory.makeConcat(MethodHandles.publicLookup(), "abc", MethodType.methodType(String.class));
另一方面,可以抛出StringConcatException
lookup
StringConcatFactory.makeConcat(MethodHandles.lookup(), "abc", MethodType.methodType(String.class));
可以正常工作,因为创建的方法句柄用于访问包的私有类的私有成员。
如@GhostCat链接的Javadoc of publicLookup中所述
publicLookup => PUBLIC_LOOKUP => (PUBLIC|UNCONDITIONAL) modes
返回最低限度受信任的查找对象。查找有
PUBLIC
和UNCONDITIONAL modes
。 它只能用于创建方法 处理包中的公共类的公共成员 无条件导出。
lookup => (lookupClass => Reflection.getCallerClass, FULL_POWER_MODES => (ALL_MODES & ~UNCONDITIONAL))
返回具有全部功能的查找对象,以模拟所有 支持调用者的字节码行为。这些功能包括 私人访问来电者。查找对象上的工厂方法可以 为调用者有权访问的任何成员创建直接方法句柄 通过字节码,包括受保护和私有字段和方法。 此查找对象是可以委派给受信任的功能 代理商。
请勿将其存储在不受信任的代码可以访问的位置。 此方法对呼叫者敏感,这意味着它可能会返回 不同的呼叫者的不同价值。
对于任何给定的调用者类C,此调用返回的查找对象 具有与JVM提供的任何查找对象相同的功能 执行的invokedynamic指令的bootstrap方法 同一个来电者C级。