If a bootstrap method declares exactly two arguments, and is
not of variable arity, then it is fed only two arguments by
the JVM, the lookup object and an instance
of BootstrapCallInfo
which supplies the rest of the
information about the call.
The API for accessing the static arguments allows the bootstrap method to reorder the resolution (in the constant pool) of the static arguments, and to catch errors resulting from the resolution. This mode of evaluation pulls bootstrap parameters from the JVM under control of the bootstrap method, as opposed to the JVM pushing parameters to a bootstrap method by resolving them all before the bootstrap method is called.
API Note
The lookup object is not included in this bundle of information, so as not to obscure the access control logic of the program. In cases where there are many thousands of parameters, it may be preferable to pull their resolved values, either singly or in batches, rather than wait until all of them have been resolved before a constant or call site can be used.
A push mode bootstrap method can be adapted to a pull mode bootstrap method, and vice versa. For example, this generic adapter pops a push-mode bootstrap method from the beginning of the static argument list, eagerly resolves all the remaining static arguments, and invokes the popped method in push mode. The callee has no way of telling that it was not called directly from the JVM.
static Object genericBSM(Lookup lookup, BootstrapCallInfo<Object> bsci) throws Throwable { ArrayList<Object> args = new ArrayList<>(); args.add(lookup); args.add(bsci.invocationName()); args.add(bsci.invocationType()); MethodHandle bsm = (MethodHandle) bsci.get(0); List<Object> restOfArgs = bsci.asList().subList(1, bsci.size(); // the next line eagerly resolves all remaining static arguments: args.addAll(restOfArgs); return bsm.invokeWithArguments(args); }
In the other direction, here is a combinator which pops
a pull-mode bootstrap method from the beginning of a list of
static argument values (already resolved), reformats all of
the arguments into a pair of a lookup and a BootstrapCallInfo
,
and invokes the popped method. Again the callee has no way of
telling it was not called directly by the JVM, except that
all of the constant values will appear as resolved.
Put another way, if any constant fails to resolve, the
callee will not be able to catch the resulting error,
since the error will be thrown by the JVM before the
bootstrap method is entered.
static Object genericBSM(Lookup lookup, String name, Object type, MethodHandle bsm, Object... args) throws Throwable { ConstantGroup cons = ConstantGroup.makeConstantGroup(Arrays.asList(args)); BootstrapCallInfo<Object> bsci = makeBootstrapCallInfo(bsm, name, type, cons); return bsm.invoke(lookup, bsci); }
Modifier and Type | Method and Description |
---|---|
public MethodHandle | |
public String | Returns: the method name or constant nameReturns the method name or constant name for this call. |
public T | Returns: the method type or constant typeReturns the method type or constant type for this call. |
public static < the type of the invocation type, either T> BootstrapCallInfoMethodHandle or Class | Returns: a new bootstrap call descriptor with the given componentsbootstrap method bsm, String invocation name name, T invocation type type, ConstantGroup the additional static arguments for the bootstrap method constants)Make a new bootstrap call descriptor with the given components. |
bootstrapMethod | back to summary |
---|---|
public MethodHandle bootstrapMethod() Returns the bootstrap method for this call.
|
invocationName | back to summary |
---|---|
public String invocationName() Returns the method name or constant name for this call.
|
invocationType | back to summary |
---|---|
public T invocationType() Returns the method type or constant type for this call.
|
makeBootstrapCallInfo | back to summary |
---|---|
public static <T> BootstrapCallInfo Make a new bootstrap call descriptor with the given components.
|