StringConcatFactory中的异常 - Java 9

时间:2017-09-05 07:13:29

标签: java java-9

在学习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

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

3 个答案:

答案 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
  

返回最低限度受信任的查找对象。查找有   PUBLICUNCONDITIONAL modes 它只能用于创建方法   处理包中的公共类的公共成员   无条件导出。

lookup

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

返回具有全部功能的查找对象,以模拟所有   支持调用者的字节码行为。这些功能包括   私人访问来电者。查找对象上的工厂方法可以   为调用者有权访问的任何成员创建直接方法句柄   通过字节码,包括受保护和私有字段和方法。   此查找对象是可以委派给受信任的功能   代理商。

     

请勿将其存储在不受信任的代码可以访问的位置。   此方法对呼叫者敏感,这意味着它可能会返回   不同的呼叫者的不同价值。

     

对于任何给定的调用者类C,此调用返回的查找对象   具有与JVM提供的任何查找对象相同的功能   执行的invokedynamic指令的bootstrap方法   同一个来电者C级。