1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.invoke; 27 28 import java.lang.invoke.MethodHandles.Lookup; 29 30 /** 31 * An interface providing full static information about a particular 32 * call to a 33 * <a href="package-summary.html#bsm">bootstrap method</a> of an 34 * dynamic call site or dynamic constant. 35 * This information includes the method itself, the associated 36 * name and type, and any associated static arguments. 37 * <p> 38 * If a bootstrap method declares exactly two arguments, and is 39 * not of variable arity, then it is fed only two arguments by 40 * the JVM, the {@linkplain Lookup lookup object} and an instance 41 * of {@code BootstrapCallInfo} which supplies the rest of the 42 * information about the call. 43 * <p> 44 * The API for accessing the static arguments allows the bootstrap 45 * method to reorder the resolution (in the constant pool) of the 46 * static arguments, and to catch errors resulting from the resolution. 47 * This mode of evaluation <em>pulls</em> bootstrap parameters from 48 * the JVM under control of the bootstrap method, as opposed to 49 * the JVM <em>pushing</em> parameters to a bootstrap method 50 * by resolving them all before the bootstrap method is called. 51 * @apiNote 52 * <p> 53 * The {@linkplain Lookup lookup object} is <em>not</em> included in this 54 * bundle of information, so as not to obscure the access control 55 * logic of the program. 56 * In cases where there are many thousands of parameters, it may 57 * be preferable to pull their resolved values, either singly or in 58 * batches, rather than wait until all of them have been resolved 59 * before a constant or call site can be used. 60 * <p> 61 * A push mode bootstrap method can be adapted to a pull mode 62 * bootstrap method, and vice versa. For example, this generic 63 * adapter pops a push-mode bootstrap method from the beginning 64 * of the static argument list, eagerly resolves all the remaining 65 * static arguments, and invokes the popped method in push mode. 66 * The callee has no way of telling that it was not called directly 67 * from the JVM. 68 * <blockquote><pre>{@code 69 static Object genericBSM(Lookup lookup, BootstrapCallInfo<Object> bsci) 70 throws Throwable { 71 ArrayList<Object> args = new ArrayList<>(); 72 args.add(lookup); 73 args.add(bsci.invocationName()); 74 args.add(bsci.invocationType()); 75 MethodHandle bsm = (MethodHandle) bsci.get(0); 76 List<Object> restOfArgs = bsci.asList().subList(1, bsci.size(); 77 // the next line eagerly resolves all remaining static arguments: 78 args.addAll(restOfArgs); 79 return bsm.invokeWithArguments(args); 80 } 81 * }</pre></blockquote> 82 * 83 * <p> 84 * In the other direction, here is a combinator which pops 85 * a pull-mode bootstrap method from the beginning of a list of 86 * static argument values (already resolved), reformats all of 87 * the arguments into a pair of a lookup and a {@code BootstrapCallInfo}, 88 * and invokes the popped method. Again the callee has no way of 89 * telling it was not called directly by the JVM, except that 90 * all of the constant values will appear as resolved. 91 * Put another way, if any constant fails to resolve, the 92 * callee will not be able to catch the resulting error, 93 * since the error will be thrown by the JVM before the 94 * bootstrap method is entered. 95 * <blockquote><pre>{@code 96 static Object genericBSM(Lookup lookup, String name, Object type, 97 MethodHandle bsm, Object... args) 98 throws Throwable { 99 ConstantGroup cons = ConstantGroup.makeConstantGroup(Arrays.asList(args)); 100 BootstrapCallInfo<Object> bsci = makeBootstrapCallInfo(bsm, name, type, cons); 101 return bsm.invoke(lookup, bsci); 102 } 103 * }</pre></blockquote> 104 * 105 * @since 1.10 106 */ 107 // public 108 interface BootstrapCallInfo<T> extends ConstantGroup { 109 /** Returns the bootstrap method for this call. 110 * @return the bootstrap method 111 */ bootstrapMethod()112 MethodHandle bootstrapMethod(); 113 114 /** Returns the method name or constant name for this call. 115 * @return the method name or constant name 116 */ invocationName()117 String invocationName(); 118 119 /** Returns the method type or constant type for this call. 120 * @return the method type or constant type 121 */ invocationType()122 T invocationType(); 123 124 /** 125 * Make a new bootstrap call descriptor with the given components. 126 * @param bsm bootstrap method 127 * @param name invocation name 128 * @param type invocation type 129 * @param constants the additional static arguments for the bootstrap method 130 * @param <T> the type of the invocation type, either {@link MethodHandle} or {@link Class} 131 * @return a new bootstrap call descriptor with the given components 132 */ makeBootstrapCallInfo(MethodHandle bsm, String name, T type, ConstantGroup constants)133 static <T> BootstrapCallInfo<T> makeBootstrapCallInfo(MethodHandle bsm, 134 String name, 135 T type, 136 ConstantGroup constants) { 137 AbstractConstantGroup.BSCIWithCache<T> bsci = new AbstractConstantGroup.BSCIWithCache<>(bsm, name, type, constants.size()); 138 final Object NP = AbstractConstantGroup.BSCIWithCache.NOT_PRESENT; 139 bsci.initializeCache(constants.asList(NP), NP); 140 return bsci; 141 } 142 } 143