java 9

2o7dmzc5  于 2021-06-30  发布在  Java
关注(0)|答案(3)|浏览(290)

在学习java9时 StringConcatFactory 类我无法理解为什么下面的代码 MethodHandles.publicLookup() 投掷 StringConcatException if时出现异常 MethodHandles.lookup() 一切正常。
根据java查找文档:
“lookup-表示具有调用者访问权限的查找上下文”

StringConcatFactory.makeConcat(MethodHandles.publicLookup(),
"abc",MethodType.methodType(String.class));//Exception Here

StringConcatFactory.makeConcat(MethodHandles.lookup(), 
"abc", MethodType.methodType(String.class)); //Working fine

我不知道我错在哪里?请帮助我理解这种行为。

0h4hbjxa

0h4hbjxa1#

的javadoc publicLookup() 说:
返回受信任度最低的查找对象。
与lookup()比较:
返回具有完全功能的查找对象,以模拟调用者的所有受支持的字节码行为。这些功能包括对调用者的私有访问。lookup对象上的工厂方法可以为调用者可以通过字节码访问的任何成员创建直接方法句柄,包括受保护的和私有的字段和方法。此查找对象是可以委派给受信任代理的功能。
和javadoc makeConcat() 最后说:
抛出StringConcateException-如果这里描述的任何链接不变量被违反。
考虑到这个问题没有包含更多的细节,最有可能的答案是:这里有某种“权限”问题。也许你试图“concat”一些在使用“最小信任”时根本不可用的东西。

bz4sfanl

bz4sfanl2#

的javadoc makeConcat 关于第一个参数:
lookup表示具有调用者访问权限的查找上下文
由返回的查找上下文 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
ldfqzlk8

ldfqzlk83#

最主要的原因是 publicLookup :

StringConcatFactory.makeConcat(MethodHandles.publicLookup(), "abc", MethodType.methodType(String.class));

可以扔一个 StringConcatException 而另一方面 lookup ```
StringConcatFactory.makeConcat(MethodHandles.lookup(), "abc", MethodType.methodType(String.class));

当创建的方法句柄用于访问包的私有类的类的私有成员时,工作正常。
正如@ghostcat链接的publicklookup的javadoc中所述

publicLookup => PUBLIC_LOOKUP => (PUBLIC|UNCONDITIONAL) modes

返回受信任度最低的查找对象。查找具有 `PUBLIC` 以及 `UNCONDITIONAL modes` . 它只能用于为无条件导出的包中的公共类的公共成员创建方法句柄。
查找时出错

lookup => (lookupClass => Reflection.getCallerClass, FULL_POWER_MODES => (ALL_MODES & ~UNCONDITIONAL))

返回具有完全功能的查找对象,以模拟调用者的所有受支持的字节码行为。这些功能包括对调用者的私有访问。lookup对象上的工厂方法可以为调用者可以通过字节码访问的任何成员创建直接方法句柄,包括受保护的和私有的字段和方法。此查找对象是可以委派给受信任代理的功能。
不要将其存储在不受信任的代码可以访问的地方。此方法对调用方敏感,这意味着它可能会向不同的调用方返回不同的值。
对于任何给定的调用方类c,此调用返回的查找对象具有与jvm提供给在同一调用方类c中执行的invokedynamic指令的引导方法的任何查找对象等效的功能。

相关问题