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 package java.lang.invoke;
26
27 import sun.invoke.util.Wrapper;
28
29 import static java.lang.invoke.MethodHandleNatives.mapLookupExceptionToError;
30 import static java.util.Objects.requireNonNull;
31
32 /**
33 * Bootstrap methods for dynamically-computed constants.
34 *
35 * <p>The bootstrap methods in this class will throw a
36 * {@code NullPointerException} for any reference argument that is {@code null},
37 * unless the argument is specified to be unused or specified to accept a
38 * {@code null} value.
39 *
40 * @since 11
41 */
42 public final class ConstantBootstraps {
43 // implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant:
44 /*non-public*/
45 static Object makeConstant(MethodHandle bootstrapMethod,
46 // Callee information:
47 String name, Class<?> type,
48 // Extra arguments for BSM, if any:
49 Object info,
50 // Caller information:
51 Class<?> callerClass) {
52 // Restrict bootstrap methods to those whose first parameter is Lookup
53 // The motivation here is, in the future, to possibly support BSMs
54 // that do not accept the meta-data of lookup/name/type, thereby
55 // allowing the co-opting of existing methods to be used as BSMs as
56 // long as the static arguments can be passed as method arguments
57 MethodType mt = bootstrapMethod.type();
58 if (mt.parameterCount() < 2 ||
59 !MethodHandles.Lookup.class.isAssignableFrom(mt.parameterType(0))) {
60 throw new BootstrapMethodError(
61 "Invalid bootstrap method declared for resolving a dynamic constant: " + bootstrapMethod);
62 }
63
64 // BSMI.invoke handles all type checking and exception translation.
65 // If type is not a reference type, the JVM is expecting a boxed
66 // version, and will manage unboxing on the other side.
67 return BootstrapMethodInvoker.invoke(
68 type, bootstrapMethod, name, type, info, callerClass);
69 }
70
71 /**
72 * Returns a {@code null} object reference for the reference type specified
73 * by {@code type}.
74 *
75 * @param lookup unused
76 * @param name unused
77 * @param type a reference type
78 * @return a {@code null} value
79 * @throws IllegalArgumentException if {@code type} is not a reference type
80 */
81 public static Object nullConstant(MethodHandles.Lookup lookup, String name, Class<?> type) {
82 if (requireNonNull(type).isPrimitive()) {
83 throw new IllegalArgumentException(String.format("not reference: %s", type));
84 }
85
86 return null;
87 }
88
89 /**
90 * Returns a {@link Class} mirror for the primitive type whose type
201 * @param type the type of the field
202 * @return the value of the field
203 * @throws IllegalAccessError if the declaring class or the field is not
204 * accessible to the class performing the operation
205 * @throws NoSuchFieldError if the specified field does not exist
206 * @throws IncompatibleClassChangeError if the specified field is not
207 * {@code final}
208 * @see #getStaticFinal(MethodHandles.Lookup, String, Class, Class)
209 */
210 public static Object getStaticFinal(MethodHandles.Lookup lookup, String name, Class<?> type) {
211 requireNonNull(type);
212
213 Class<?> declaring = type.isPrimitive()
214 ? Wrapper.forPrimitiveType(type).wrapperType()
215 : type;
216 return getStaticFinal(lookup, name, type, declaring);
217 }
218
219
220 /**
221 * Returns the result of invoking a method handle with the provided
222 * arguments.
223 * <p>
224 * This method behaves as if the method handle to be invoked is the result
225 * of adapting the given method handle, via {@link MethodHandle#asType}, to
226 * adjust the return type to the desired type.
227 *
228 * @param lookup unused
229 * @param name unused
230 * @param type the desired type of the value to be returned, which must be
231 * compatible with the return type of the method handle
232 * @param handle the method handle to be invoked
233 * @param args the arguments to pass to the method handle, as if with
234 * {@link MethodHandle#invokeWithArguments}. Each argument may be
235 * {@code null}.
236 * @return the result of invoking the method handle
237 * @throws WrongMethodTypeException if the handle's method type cannot be
238 * adjusted to take the given number of arguments, or if the handle's return
239 * type cannot be adjusted to the desired type
240 * @throws ClassCastException if an argument or the result produced by
241 * invoking the handle cannot be converted by reference casting
242 * @throws Throwable anything thrown by the method handle invocation
243 */
244 public static Object invoke(MethodHandles.Lookup lookup, String name, Class<?> type,
245 MethodHandle handle, Object... args) throws Throwable {
246 requireNonNull(type);
247 requireNonNull(handle);
248 requireNonNull(args);
249
250 if (type != handle.type().returnType()) {
251 // Adjust the return type of the handle to be invoked while
252 // preserving variable arity if present
253 handle = handle.asType(handle.type().changeReturnType(type)).
254 withVarargs(handle.isVarargsCollector());
255 }
256
257 return handle.invokeWithArguments(args);
258 }
259
260 /**
261 * Finds a {@link VarHandle} for an instance field.
262 *
263 * @param lookup the lookup context describing the class performing the
264 * operation (normally stacked by the JVM)
265 * @param name the name of the field
266 * @param type the required result type (must be {@code Class<VarHandle>})
267 * @param declaringClass the class in which the field is declared
268 * @param fieldType the type of the field
269 * @return the {@link VarHandle}
270 * @throws IllegalAccessError if the declaring class or the field is not
271 * accessible to the class performing the operation
272 * @throws NoSuchFieldError if the specified field does not exist
273 * @throws IllegalArgumentException if the type is not {@code VarHandle}
274 */
275 public static VarHandle fieldVarHandle(MethodHandles.Lookup lookup, String name, Class<VarHandle> type,
276 Class<?> declaringClass, Class<?> fieldType) {
277 requireNonNull(lookup);
|
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 package java.lang.invoke;
26
27 import sun.invoke.util.Wrapper;
28
29 import java.lang.constant.ConstantDesc;
30 import java.util.Arrays;
31
32 import static java.lang.invoke.AbstractBootstrapCallInfo.maybeShareArguments;
33 import static java.lang.invoke.BootstrapMethodInvoker.invokeCommon;
34 import static java.lang.invoke.MethodHandleNatives.mapLookupExceptionToError;
35 import static java.lang.invoke.MethodHandles.Lookup;
36 import static java.util.Objects.requireNonNull;
37
38 /**
39 * Bootstrap methods for dynamically-computed constants.
40 *
41 * <p>The bootstrap methods in this class will throw a
42 * {@code NullPointerException} for any reference argument that is {@code null},
43 * unless the argument is specified to be unused or specified to accept a
44 * {@code null} value.
45 *
46 * @since 11
47 */
48 public final class ConstantBootstraps {
49 /**
50 * Returns a {@code null} object reference for the reference type specified
51 * by {@code type}.
52 *
53 * @param lookup unused
54 * @param name unused
55 * @param type a reference type
56 * @return a {@code null} value
57 * @throws IllegalArgumentException if {@code type} is not a reference type
58 */
59 public static Object nullConstant(MethodHandles.Lookup lookup, String name, Class<?> type) {
60 if (requireNonNull(type).isPrimitive()) {
61 throw new IllegalArgumentException(String.format("not reference: %s", type));
62 }
63
64 return null;
65 }
66
67 /**
68 * Returns a {@link Class} mirror for the primitive type whose type
179 * @param type the type of the field
180 * @return the value of the field
181 * @throws IllegalAccessError if the declaring class or the field is not
182 * accessible to the class performing the operation
183 * @throws NoSuchFieldError if the specified field does not exist
184 * @throws IncompatibleClassChangeError if the specified field is not
185 * {@code final}
186 * @see #getStaticFinal(MethodHandles.Lookup, String, Class, Class)
187 */
188 public static Object getStaticFinal(MethodHandles.Lookup lookup, String name, Class<?> type) {
189 requireNonNull(type);
190
191 Class<?> declaring = type.isPrimitive()
192 ? Wrapper.forPrimitiveType(type).wrapperType()
193 : type;
194 return getStaticFinal(lookup, name, type, declaring);
195 }
196
197
198 /**
199 * Returns the result of invoking a bootstrap method handle on static
200 * arguments, but without metadata.
201 * <p>
202 * This method behaves as if the method handle to be invoked is the result
203 * of adapting the given method handle, via {@link MethodHandle#asType}, to
204 * adjust the return type to {@code invocationType} of the bootstrap call.
205 *
206 * @param lookup unused
207 * @param name unused
208 * @param type the desired type of the value to be returned, which must be
209 * compatible with the return type of the method handle
210 * @param handle the method handle to be invoked
211 * @param args the arguments to pass to the method handle, as if with
212 * {@link MethodHandle#invokeWithArguments}. Each argument may be
213 * {@code null}.
214 * @return the result of invoking the method handle
215 * @throws WrongMethodTypeException if the handle's method type cannot be
216 * adjusted to take the given number of arguments, or if the handle's return
217 * type cannot be adjusted to the desired type
218 * @throws ClassCastException if an argument or the result produced by
219 * invoking the handle cannot be converted by reference casting
220 * @throws Throwable anything thrown by the method handle invocation
221 */
222 public static Object invoke(MethodHandles.Lookup lookup, String name, Class<?> type,
223 MethodHandle handle, Object... args) throws Throwable {
224 requireNonNull(type);
225 requireNonNull(handle);
226 requireNonNull(args);
227
228 Object result = invokeCommon(handle, null, null, null, args, null);
229 return BootstrapCallInfo.convertResult(type, handle.type().returnType(), result);
230 }
231
232 /**
233 * Returns the result of invoking a bootstrap method handle on static
234 * arguments, but without metadata.
235 * <p>
236 * This method behaves as if the method handle to be invoked is the result
237 * of adapting the given method handle, via {@link MethodHandle#asType}, to
238 * adjust the return type to {@code invocationType} of the bootstrap call.
239 *
240 * @param lookup unused
241 * @param bsci the container of the bootstrap method
242 * @return the result of invoking the method handle
243 * @throws WrongMethodTypeException if the handle's method type cannot be
244 * adjusted to take the given number of arguments, or if the handle's return
245 * type cannot be adjusted to the desired type
246 * @throws ClassCastException if an argument or the result produced by
247 * invoking the handle cannot be converted by reference casting
248 * @throws Throwable anything thrown by the method handle invocation
249 */
250 // not public until BootstrapCallInfo is public
251 static Object invoke(MethodHandles.Lookup lookup, BootstrapCallInfo<?> bsci) throws Throwable {
252 MethodHandle bsm = bsci.bootstrapMethod();
253 Object result = invokeCommon(bsm,
254 null, null, null,
255 maybeShareArguments(bsci),
256 bsci.argumentList());
257 return BootstrapCallInfo.convertResult((Class<?>) bsci.invocationType(), bsm.type().returnType(), result);
258 }
259
260 /**
261 * Returns the result of invoking a bootstrap method handle on static
262 * arguments, but without metadata. In addition, any arguments of type
263 * {@code Object} or of any type assignable to {@code ConstantDesc} will
264 * be provided symbolic references, rather than resolved values, for
265 * the corresponding static arguments.
266 * <p>
267 * Finally, any single argument of type {@code Lookup} will be passed the
268 * lookup object directly, rather than either a symbolic reference or
269 * resolved argument value.
270 * <p>
271 * This method behaves as if the method handle to be invoked is the result
272 * of adapting the given method handle, via {@link MethodHandle#asType}, to
273 * adjust the return type to {@code invocationType} of the bootstrap call.
274 *
275 * @param lookup unused
276 * @param bsci the container of the bootstrap method
277 * @return the result of invoking the method handle
278 * @throws WrongMethodTypeException if the handle's method type cannot be
279 * adjusted to take the given number of arguments, or if the handle's return
280 * type cannot be adjusted to the desired type
281 * @throws ClassCastException if an argument or the result produced by
282 * invoking the handle cannot be converted by reference casting
283 * @throws Throwable anything thrown by the method handle invocation
284 */
285 // not public until BootstrapCallInfo is public
286 static Object symbolic(MethodHandles.Lookup lookup, BootstrapCallInfo<?> bsci) throws Throwable {
287 MethodHandle bsm = bsci.bootstrapMethod();
288 MethodType bsmType = bsm.type();
289 boolean passLookup = bsmType.parameterList().contains(Lookup.class);
290 Object[] argv = new Object[bsci.argumentCount() + (passLookup ? 1 : 0)];
291 int pos = 0;
292 int maxPos = bsmType.parameterCount() - (bsm.isVarargsCollector() ? 1 : 0);
293 int bargPos = 0;
294 for (Class<?> ptype : bsmType.parameterList()) {
295 if (pos == maxPos) break;
296 if (ptype == Lookup.class && passLookup) {
297 argv[pos++] = lookup;
298 passLookup = false;
299 } else if (isSymbolicArgType(ptype)) {
300 argv[pos++] = bsci.argumentDesc(bargPos++);
301 } else {
302 argv[pos++] = bsci.argument(bargPos++);
303 }
304 }
305 Class<?> ptype = bsmType.lastParameterType().componentType();
306 while (pos < argv.length) {
307 assert(ptype != null);
308 if (isSymbolicArgType(ptype)) {
309 argv[pos++] = bsci.argumentDesc(bargPos++);
310 } else {
311 argv[pos++] = bsci.argument(bargPos++);
312 }
313 }
314 Object result = invokeCommon(bsm,
315 null, null, null,
316 argv, null);
317 return BootstrapCallInfo.convertResult((Class<?>)bsci.invocationType(), bsmType.returnType(), result);
318 }
319
320 private static boolean isSymbolicArgType(Class<?> ptype) {
321 return (ptype == Object.class || ConstantDesc.class.isAssignableFrom(ptype));
322 }
323
324 /**
325 * Trivial method which returns its sole argument, which must be a
326 * ConstantDesc of some sort. This method is useful as an
327 * expression-mode bootstrap method with the operation "symbolic".
328 *
329 * @param desc the value to be returned
330 * @param <T> the type of the value to be returned
331 * @return desc
332 * @see DynamicConstantDesc#ofSymbolic
333 */
334 public static <T extends ConstantDesc<?>> T constantDesc(T desc) {
335 return desc;
336 }
337
338 /**
339 * Returns the result of invoking a bootstrap method handle in
340 * expression mode. The exact behavior of this mode depends on
341 * the {@code name} string. If the name is {@code "invoke"},
342 * then the bootstrap method is applied directly to the arguments,
343 * as if it were the leading static argument to {@link #invoke}.
344 * If the name is {@code "symbolic"} then bootstrap arguments
345 * are extracted as unresolved symbolic references from the
346 * constant pool and returned.
347 * Other {@code name} strings are reserved for future use.
348 * <p>
349 * @apiNote
350 * This method behaves like the following:
351 * <blockquote><pre>{@code
352 String name = bsci.invocationName();
353 switch (name) {
354 case "invoke": return invoke(lookup, bsci);
355 case "symbolic": return symbolic(lookup, bsci);
356 }
357 * }</pre></blockquote>
358 * <p>
359 *
360 * @param lookup must be non-null, otherwise presently unused
361 * @param bsci bootstrap call information
362 * @return the result of invoking the bootstrap method handle on appropriate arguments
363 * @throws WrongMethodTypeException if the handle's method type cannot be
364 * adjusted to take the given number of arguments, or if the handle's return
365 * type cannot be adjusted to the desired type
366 * @throws ClassCastException if an argument or the result produced by
367 * invoking the handle cannot be converted by reference casting
368 * @throws IllegalArgumentException if the {@code name} is invalid
369 * @throws Throwable anything thrown by an action selected by {@code name}
370 */
371 // not public until BootstrapCallInfo is public
372 static Object linkExpression(MethodHandles.Lookup lookup,
373 BootstrapCallInfo<?> bsci) throws Throwable {
374 requireNonNull(lookup);
375 requireNonNull(bsci);
376
377 String name = bsci.invocationName();
378 switch (name) {
379 case "invoke": return invoke(lookup, bsci);
380 case "symbolic": return symbolic(lookup, bsci);
381 }
382
383 throw new IllegalArgumentException("invalid name for expression-mode constant: "+bsci);
384 }
385
386 /**
387 * Finds a {@link VarHandle} for an instance field.
388 *
389 * @param lookup the lookup context describing the class performing the
390 * operation (normally stacked by the JVM)
391 * @param name the name of the field
392 * @param type the required result type (must be {@code Class<VarHandle>})
393 * @param declaringClass the class in which the field is declared
394 * @param fieldType the type of the field
395 * @return the {@link VarHandle}
396 * @throws IllegalAccessError if the declaring class or the field is not
397 * accessible to the class performing the operation
398 * @throws NoSuchFieldError if the specified field does not exist
399 * @throws IllegalArgumentException if the type is not {@code VarHandle}
400 */
401 public static VarHandle fieldVarHandle(MethodHandles.Lookup lookup, String name, Class<VarHandle> type,
402 Class<?> declaringClass, Class<?> fieldType) {
403 requireNonNull(lookup);
|