250 public final class LambdaMetafactory {
251
252 private LambdaMetafactory() {}
253
254 /** Flag for {@link #altMetafactory} indicating the lambda object
255 * must be serializable */
256 public static final int FLAG_SERIALIZABLE = 1 << 0;
257
258 /**
259 * Flag for {@link #altMetafactory} indicating the lambda object implements
260 * other interfaces besides {@code Serializable}
261 */
262 public static final int FLAG_MARKERS = 1 << 1;
263
264 /**
265 * Flag for alternate metafactories indicating the lambda object requires
266 * additional methods that invoke the {@code implementation}
267 */
268 public static final int FLAG_BRIDGES = 1 << 2;
269
270 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
271 private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
272
273 // LambdaMetafactory bootstrap methods are startup sensitive, and may be
274 // special cased in java.lang.invoke.BootstrapMethodInvoker to ensure
275 // methods are invoked with exact type information to avoid generating
276 // code for runtime checks. Take care any changes or additions here are
277 // reflected there as appropriate.
278
279 /**
280 * Facilitates the creation of simple "function objects" that implement one
281 * or more interfaces by delegation to a provided {@link MethodHandle},
282 * after appropriate type adaptation and partial evaluation of arguments.
283 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
284 * call sites, to support the <em>lambda expression</em> and <em>method
285 * reference expression</em> features of the Java Programming Language.
286 *
287 * <p>This is the standard, streamlined metafactory; additional flexibility
288 * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
289 * A general description of the behavior of this method is provided
332 * handle referencing a method or constructor, or if the linkage
333 * invariants are violated, as defined {@link LambdaMetafactory above}.
334 * @throws NullPointerException If any argument is {@code null}.
335 */
336 public static CallSite metafactory(MethodHandles.Lookup caller,
337 String interfaceMethodName,
338 MethodType factoryType,
339 MethodType interfaceMethodType,
340 MethodHandle implementation,
341 MethodType dynamicMethodType)
342 throws LambdaConversionException {
343 AbstractValidatingLambdaMetafactory mf;
344 mf = new InnerClassLambdaMetafactory(Objects.requireNonNull(caller),
345 Objects.requireNonNull(factoryType),
346 Objects.requireNonNull(interfaceMethodName),
347 Objects.requireNonNull(interfaceMethodType),
348 Objects.requireNonNull(implementation),
349 Objects.requireNonNull(dynamicMethodType),
350 false,
351 EMPTY_CLASS_ARRAY,
352 EMPTY_MT_ARRAY);
353 mf.validateMetafactoryArgs();
354 return mf.buildCallSite();
355 }
356
357 /**
358 * Facilitates the creation of simple "function objects" that implement one
359 * or more interfaces by delegation to a provided {@link MethodHandle},
360 * after appropriate type adaptation and partial evaluation of arguments.
361 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
362 * call sites, to support the <em>lambda expression</em> and <em>method
363 * reference expression</em> features of the Java Programming Language.
364 *
365 * <p>This is the general, more flexible metafactory; a streamlined version
366 * is provided by {@link #metafactory(java.lang.invoke.MethodHandles.Lookup,
367 * String, MethodType, MethodType, MethodHandle, MethodType)}.
368 * A general description of the behavior of this method is provided
369 * {@link LambdaMetafactory above}.
370 *
371 * <p>The argument list for this method includes three fixed parameters,
372 * corresponding to the parameters automatically stacked by the VM for the
378 * CallSite altMetafactory(MethodHandles.Lookup caller,
379 * String interfaceMethodName,
380 * MethodType factoryType,
381 * Object... args)
382 * }</pre>
383 *
384 * <p>but it behaves as if the argument list is as follows:
385 *
386 * <pre>{@code
387 * CallSite altMetafactory(MethodHandles.Lookup caller,
388 * String interfaceMethodName,
389 * MethodType factoryType,
390 * MethodType interfaceMethodType,
391 * MethodHandle implementation,
392 * MethodType dynamicMethodType,
393 * int flags,
394 * int altInterfaceCount, // IF flags has MARKERS set
395 * Class... altInterfaces, // IF flags has MARKERS set
396 * int altMethodCount, // IF flags has BRIDGES set
397 * MethodType... altMethods // IF flags has BRIDGES set
398 * )
399 * }</pre>
400 *
401 * <p>Arguments that appear in the argument list for
402 * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
403 * have the same specification as in that method. The additional arguments
404 * are interpreted as follows:
405 * <ul>
406 * <li>{@code flags} indicates additional options; this is a bitwise
407 * OR of desired flags. Defined flags are {@link #FLAG_BRIDGES},
408 * {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
409 * <li>{@code altInterfaceCount} is the number of additional interfaces
410 * the function object should implement, and is present if and only if the
411 * {@code FLAG_MARKERS} flag is set.</li>
412 * <li>{@code altInterfaces} is a variable-length list of additional
413 * interfaces to implement, whose length equals {@code altInterfaceCount},
414 * and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
415 * <li>{@code altMethodCount} is the number of additional method signatures
416 * the function object should implement, and is present if and only if
417 * the {@code FLAG_BRIDGES} flag is set.</li>
418 * <li>{@code altMethods} is a variable-length list of additional
419 * methods signatures to implement, whose length equals {@code altMethodCount},
420 * and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
421 * </ul>
422 *
423 * <p>Each class named by {@code altInterfaces} is subject to the same
424 * restrictions as {@code Rd}, the return type of {@code factoryType},
425 * as described {@link LambdaMetafactory above}. Each {@code MethodType}
426 * named by {@code altMethods} is subject to the same restrictions as
427 * {@code interfaceMethodType}, as described {@link LambdaMetafactory above}.
428 *
429 * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
430 * will implement {@code Serializable}, and will have a {@code writeReplace}
431 * method that returns an appropriate {@link SerializedLambda}. The
432 * {@code caller} class must have an appropriate {@code $deserializeLambda$}
433 * method, as described in {@link SerializedLambda}.
434 *
435 * <p>When the target of the {@code CallSite} returned from this method is
436 * invoked, the resulting function objects are instances of a class with
437 * the following properties:
438 * <ul>
439 * <li>The class implements the interface named by the return type
440 * of {@code factoryType} and any interfaces named by {@code altInterfaces}</li>
441 * <li>The class declares methods with the name given by {@code interfaceMethodName},
442 * and the signature given by {@code interfaceMethodType} and additional signatures
443 * given by {@code altMethods}</li>
444 * <li>The class may override methods from {@code Object}, and may
445 * implement methods related to serialization.</li>
446 * </ul>
447 *
448 * @param caller Represents a lookup context with the accessibility
449 * privileges of the caller. Specifically, the lookup context
450 * must have {@linkplain MethodHandles.Lookup#hasFullPrivilegeAccess()
451 * full privilege access}.
452 * When used with {@code invokedynamic}, this is stacked
453 * automatically by the VM.
454 * @param interfaceMethodName The name of the method to implement. When used with
480 * of {@code args} do not follow the above rules, or if
481 * {@code altInterfaceCount} or {@code altMethodCount} are negative
482 * integers.
483 */
484 public static CallSite altMetafactory(MethodHandles.Lookup caller,
485 String interfaceMethodName,
486 MethodType factoryType,
487 Object... args)
488 throws LambdaConversionException {
489 Objects.requireNonNull(caller);
490 Objects.requireNonNull(interfaceMethodName);
491 Objects.requireNonNull(factoryType);
492 Objects.requireNonNull(args);
493 int argIndex = 0;
494 MethodType interfaceMethodType = extractArg(args, argIndex++, MethodType.class);
495 MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
496 MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
497 int flags = extractArg(args, argIndex++, Integer.class);
498 Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
499 MethodType[] altMethods = EMPTY_MT_ARRAY;
500 if ((flags & FLAG_MARKERS) != 0) {
501 int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
502 if (altInterfaceCount < 0) {
503 throw new IllegalArgumentException("negative argument count");
504 }
505 if (altInterfaceCount > 0) {
506 altInterfaces = extractArgs(args, argIndex, Class.class, altInterfaceCount);
507 argIndex += altInterfaceCount;
508 }
509 }
510 if ((flags & FLAG_BRIDGES) != 0) {
511 int altMethodCount = extractArg(args, argIndex++, Integer.class);
512 if (altMethodCount < 0) {
513 throw new IllegalArgumentException("negative argument count");
514 }
515 if (altMethodCount > 0) {
516 altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
517 argIndex += altMethodCount;
518 }
519 }
520 if (argIndex < args.length) {
521 throw new IllegalArgumentException("too many arguments");
522 }
523
524 boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
525 if (isSerializable) {
526 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(factoryType.returnType());
527 for (Class<?> c : altInterfaces)
528 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
529 if (!foundSerializableSupertype) {
530 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
531 altInterfaces[altInterfaces.length-1] = Serializable.class;
532 }
533 }
534
535 AbstractValidatingLambdaMetafactory mf
536 = new InnerClassLambdaMetafactory(caller,
537 factoryType,
538 interfaceMethodName,
539 interfaceMethodType,
540 implementation,
541 dynamicMethodType,
542 isSerializable,
543 altInterfaces,
544 altMethods);
545 mf.validateMetafactoryArgs();
546 return mf.buildCallSite();
547 }
548
549 private static <T> T extractArg(Object[] args, int index, Class<T> type) {
550 if (index >= args.length) {
551 throw new IllegalArgumentException("missing argument");
552 }
553 Object result = Objects.requireNonNull(args[index]);
554 if (!type.isInstance(result)) {
555 throw new IllegalArgumentException("argument has wrong type");
556 }
557 return type.cast(result);
558 }
559
560 private static <T> T[] extractArgs(Object[] args, int index, Class<T> type, int count) {
561 @SuppressWarnings("unchecked")
562 T[] result = (T[]) Array.newInstance(type, count);
563 for (int i = 0; i < count; i++) {
564 result[i] = extractArg(args, index + i, type);
|
250 public final class LambdaMetafactory {
251
252 private LambdaMetafactory() {}
253
254 /** Flag for {@link #altMetafactory} indicating the lambda object
255 * must be serializable */
256 public static final int FLAG_SERIALIZABLE = 1 << 0;
257
258 /**
259 * Flag for {@link #altMetafactory} indicating the lambda object implements
260 * other interfaces besides {@code Serializable}
261 */
262 public static final int FLAG_MARKERS = 1 << 1;
263
264 /**
265 * Flag for alternate metafactories indicating the lambda object requires
266 * additional methods that invoke the {@code implementation}
267 */
268 public static final int FLAG_BRIDGES = 1 << 2;
269
270 /** Flag for {@link #altMetafactory} indicating the lambda object
271 * must be a {@code Quotable} object, inspectable using code reflection. */
272 public static final int FLAG_QUOTABLE = 1 << 3;
273
274 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
275 private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
276
277 // LambdaMetafactory bootstrap methods are startup sensitive, and may be
278 // special cased in java.lang.invoke.BootstrapMethodInvoker to ensure
279 // methods are invoked with exact type information to avoid generating
280 // code for runtime checks. Take care any changes or additions here are
281 // reflected there as appropriate.
282
283 /**
284 * Facilitates the creation of simple "function objects" that implement one
285 * or more interfaces by delegation to a provided {@link MethodHandle},
286 * after appropriate type adaptation and partial evaluation of arguments.
287 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
288 * call sites, to support the <em>lambda expression</em> and <em>method
289 * reference expression</em> features of the Java Programming Language.
290 *
291 * <p>This is the standard, streamlined metafactory; additional flexibility
292 * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
293 * A general description of the behavior of this method is provided
336 * handle referencing a method or constructor, or if the linkage
337 * invariants are violated, as defined {@link LambdaMetafactory above}.
338 * @throws NullPointerException If any argument is {@code null}.
339 */
340 public static CallSite metafactory(MethodHandles.Lookup caller,
341 String interfaceMethodName,
342 MethodType factoryType,
343 MethodType interfaceMethodType,
344 MethodHandle implementation,
345 MethodType dynamicMethodType)
346 throws LambdaConversionException {
347 AbstractValidatingLambdaMetafactory mf;
348 mf = new InnerClassLambdaMetafactory(Objects.requireNonNull(caller),
349 Objects.requireNonNull(factoryType),
350 Objects.requireNonNull(interfaceMethodName),
351 Objects.requireNonNull(interfaceMethodType),
352 Objects.requireNonNull(implementation),
353 Objects.requireNonNull(dynamicMethodType),
354 false,
355 EMPTY_CLASS_ARRAY,
356 EMPTY_MT_ARRAY,
357 null);
358 mf.validateMetafactoryArgs();
359 return mf.buildCallSite();
360 }
361
362 /**
363 * Facilitates the creation of simple "function objects" that implement one
364 * or more interfaces by delegation to a provided {@link MethodHandle},
365 * after appropriate type adaptation and partial evaluation of arguments.
366 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
367 * call sites, to support the <em>lambda expression</em> and <em>method
368 * reference expression</em> features of the Java Programming Language.
369 *
370 * <p>This is the general, more flexible metafactory; a streamlined version
371 * is provided by {@link #metafactory(java.lang.invoke.MethodHandles.Lookup,
372 * String, MethodType, MethodType, MethodHandle, MethodType)}.
373 * A general description of the behavior of this method is provided
374 * {@link LambdaMetafactory above}.
375 *
376 * <p>The argument list for this method includes three fixed parameters,
377 * corresponding to the parameters automatically stacked by the VM for the
383 * CallSite altMetafactory(MethodHandles.Lookup caller,
384 * String interfaceMethodName,
385 * MethodType factoryType,
386 * Object... args)
387 * }</pre>
388 *
389 * <p>but it behaves as if the argument list is as follows:
390 *
391 * <pre>{@code
392 * CallSite altMetafactory(MethodHandles.Lookup caller,
393 * String interfaceMethodName,
394 * MethodType factoryType,
395 * MethodType interfaceMethodType,
396 * MethodHandle implementation,
397 * MethodType dynamicMethodType,
398 * int flags,
399 * int altInterfaceCount, // IF flags has MARKERS set
400 * Class... altInterfaces, // IF flags has MARKERS set
401 * int altMethodCount, // IF flags has BRIDGES set
402 * MethodType... altMethods // IF flags has BRIDGES set
403 * MethodHandle quotableField // IF flags has QUOTABLE set
404 * )
405 * }</pre>
406 *
407 * <p>Arguments that appear in the argument list for
408 * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
409 * have the same specification as in that method. The additional arguments
410 * are interpreted as follows:
411 * <ul>
412 * <li>{@code flags} indicates additional options; this is a bitwise
413 * OR of desired flags. Defined flags are {@link #FLAG_BRIDGES},
414 * {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
415 * <li>{@code altInterfaceCount} is the number of additional interfaces
416 * the function object should implement, and is present if and only if the
417 * {@code FLAG_MARKERS} flag is set.</li>
418 * <li>{@code altInterfaces} is a variable-length list of additional
419 * interfaces to implement, whose length equals {@code altInterfaceCount},
420 * and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
421 * <li>{@code altMethodCount} is the number of additional method signatures
422 * the function object should implement, and is present if and only if
423 * the {@code FLAG_BRIDGES} flag is set.</li>
424 * <li>{@code altMethods} is a variable-length list of additional
425 * methods signatures to implement, whose length equals {@code altMethodCount},
426 * and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
427 * <li>{@code quotableField} is a
428 * {@linkplain MethodHandles.Lookup#findGetter(Class, String, Class) getter} method handle
429 * that is used to retrieve the string representation of the quotable lambda's associated
430 * intermediate representation.</li>
431 * </ul>
432 *
433 * <p>Each class named by {@code altInterfaces} is subject to the same
434 * restrictions as {@code Rd}, the return type of {@code factoryType},
435 * as described {@link LambdaMetafactory above}. Each {@code MethodType}
436 * named by {@code altMethods} is subject to the same restrictions as
437 * {@code interfaceMethodType}, as described {@link LambdaMetafactory above}.
438 *
439 * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
440 * will implement {@code Serializable}, and will have a {@code writeReplace}
441 * method that returns an appropriate {@link SerializedLambda}. The
442 * {@code caller} class must have an appropriate {@code $deserializeLambda$}
443 * method, as described in {@link SerializedLambda}.
444 *
445 * <p>When FLAG_QUOTABLE is set in {@code flags}, the function objects
446 * will implement {@code Quotable}.
447 *
448 * <p>When the target of the {@code CallSite} returned from this method is
449 * invoked, the resulting function objects are instances of a class with
450 * the following properties:
451 * <ul>
452 * <li>The class implements the interface named by the return type
453 * of {@code factoryType} and any interfaces named by {@code altInterfaces}</li>
454 * <li>The class declares methods with the name given by {@code interfaceMethodName},
455 * and the signature given by {@code interfaceMethodType} and additional signatures
456 * given by {@code altMethods}</li>
457 * <li>The class may override methods from {@code Object}, and may
458 * implement methods related to serialization.</li>
459 * </ul>
460 *
461 * @param caller Represents a lookup context with the accessibility
462 * privileges of the caller. Specifically, the lookup context
463 * must have {@linkplain MethodHandles.Lookup#hasFullPrivilegeAccess()
464 * full privilege access}.
465 * When used with {@code invokedynamic}, this is stacked
466 * automatically by the VM.
467 * @param interfaceMethodName The name of the method to implement. When used with
493 * of {@code args} do not follow the above rules, or if
494 * {@code altInterfaceCount} or {@code altMethodCount} are negative
495 * integers.
496 */
497 public static CallSite altMetafactory(MethodHandles.Lookup caller,
498 String interfaceMethodName,
499 MethodType factoryType,
500 Object... args)
501 throws LambdaConversionException {
502 Objects.requireNonNull(caller);
503 Objects.requireNonNull(interfaceMethodName);
504 Objects.requireNonNull(factoryType);
505 Objects.requireNonNull(args);
506 int argIndex = 0;
507 MethodType interfaceMethodType = extractArg(args, argIndex++, MethodType.class);
508 MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
509 MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
510 int flags = extractArg(args, argIndex++, Integer.class);
511 Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
512 MethodType[] altMethods = EMPTY_MT_ARRAY;
513 // Getter that returns the op of a Quotable instance
514 MethodHandle quotableOpGetter = null;
515 if ((flags & FLAG_MARKERS) != 0) {
516 int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
517 if (altInterfaceCount < 0) {
518 throw new IllegalArgumentException("negative argument count");
519 }
520 if (altInterfaceCount > 0) {
521 altInterfaces = extractArgs(args, argIndex, Class.class, altInterfaceCount);
522 argIndex += altInterfaceCount;
523 }
524 }
525 if ((flags & FLAG_BRIDGES) != 0) {
526 int altMethodCount = extractArg(args, argIndex++, Integer.class);
527 if (altMethodCount < 0) {
528 throw new IllegalArgumentException("negative argument count");
529 }
530 if (altMethodCount > 0) {
531 altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
532 argIndex += altMethodCount;
533 }
534 }
535 if ((flags & FLAG_QUOTABLE) != 0) {
536 quotableOpGetter = extractArg(args, argIndex++, MethodHandle.class);
537 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
538 altInterfaces[altInterfaces.length-1] = InnerClassLambdaMetafactory.CodeReflectionSupport.QUOTABLE_CLASS;
539 }
540 if (argIndex < args.length) {
541 throw new IllegalArgumentException("too many arguments");
542 }
543
544 boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
545 if (isSerializable) {
546 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(factoryType.returnType());
547 for (Class<?> c : altInterfaces)
548 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
549 if (!foundSerializableSupertype) {
550 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
551 altInterfaces[altInterfaces.length-1] = Serializable.class;
552 }
553 }
554
555 AbstractValidatingLambdaMetafactory mf
556 = new InnerClassLambdaMetafactory(caller,
557 factoryType,
558 interfaceMethodName,
559 interfaceMethodType,
560 implementation,
561 dynamicMethodType,
562 isSerializable,
563 altInterfaces,
564 altMethods,
565 quotableOpGetter);
566 mf.validateMetafactoryArgs();
567 return mf.buildCallSite();
568 }
569
570 private static <T> T extractArg(Object[] args, int index, Class<T> type) {
571 if (index >= args.length) {
572 throw new IllegalArgumentException("missing argument");
573 }
574 Object result = Objects.requireNonNull(args[index]);
575 if (!type.isInstance(result)) {
576 throw new IllegalArgumentException("argument has wrong type");
577 }
578 return type.cast(result);
579 }
580
581 private static <T> T[] extractArgs(Object[] args, int index, Class<T> type, int count) {
582 @SuppressWarnings("unchecked")
583 T[] result = (T[]) Array.newInstance(type, count);
584 for (int i = 0; i < count; i++) {
585 result[i] = extractArg(args, index + i, type);
|