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