While learning java9 StringConcatFactory
class I am unable to understand why following code with MethodHandles.publicLookup()
throws StringConcatException
exception while if MethodHandles.lookup()
is used everything is working fine.
As per java docs of lookup:
"lookup - Represents a lookup context with the accessibility privileges of the caller"
StringConcatFactory.makeConcat(MethodHandles.publicLookup(),
"abc",MethodType.methodType(String.class));//Exception Here
StringConcatFactory.makeConcat(MethodHandles.lookup(),
"abc", MethodType.methodType(String.class)); //Working fine
I am not sure where I am mistaken? Please help me understand this behavior.
The javadoc for makeConcat
says about the first parameter:
lookup Represents a lookup context with the accessibility privileges of the caller
The lookup context returned by publicLookup
does not have those privileges.
Even if you concatenate nothing, the exception will still be thrown:
MethodType concatType = MethodType.methodType(String.class); // No arguments, returns String
StringConcatFactory.makeConcat(MethodHandles.publicLookup(), "abc", concatType); // Exception
Because the access privileges of the context are checked in StringConcatFactory#doStringConcat
:
if ((lookup.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
throw new StringConcatException("Invalid caller: " +
lookup.lookupClass().getName());
}
The context needs a private lookup mode, and a publicLookup
does not have it:
System.out.println((MethodHandles.publicLookup().lookupModes()
& MethodHandles.Lookup.PRIVATE) != 0); // false
System.out.println((MethodHandles.lookup().lookupModes()
& MethodHandles.Lookup.PRIVATE) != 0); // true