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.io.Serializable;
29 import java.util.Arrays;
30 import java.lang.reflect.Array;
31 import java.util.Objects;
32
33 import jdk.internal.vm.annotation.AOTSafeClassInitializer;
34
35 /**
36 * <p>Methods to facilitate the creation of simple "function objects" that
37 * implement one or more interfaces by delegation to a provided {@link MethodHandle},
38 * possibly after type adaptation and partial evaluation of arguments. These
39 * methods are typically used as <em>bootstrap methods</em> for {@code invokedynamic}
40 * call sites, to support the <em>lambda expression</em> and <em>method
41 * reference expression</em> features of the Java Programming Language.
42 *
43 * <p>Indirect access to the behavior specified by the provided {@code MethodHandle}
44 * proceeds in order through three phases:
45 * <ul>
46 * <li><p><em>Linkage</em> occurs when the methods in this class are invoked.
47 * They take as arguments an interface to be implemented (typically a
48 * <em>functional interface</em>, one with a single abstract method), a
49 * name and signature of a method from that interface to be implemented, a
50 * {@linkplain MethodHandleInfo direct method handle} describing the desired
51 * implementation behavior for that method, and possibly other additional
52 * metadata, and produce a {@link CallSite} whose target can be used to
326 * be enforced dynamically at invocation time.
327 * In simple use cases this is the same as
328 * {@code interfaceMethodType}.
329 * @return a CallSite whose target can be used to perform capture, generating
330 * instances of the interface named by {@code factoryType}
331 * @throws LambdaConversionException If {@code caller} does not have full privilege
332 * access, or if {@code interfaceMethodName} is not a valid JVM
333 * method name, or if the return type of {@code factoryType} is not
334 * an interface, or if {@code implementation} is not a direct method
335 * handle referencing a method or constructor, or if the linkage
336 * invariants are violated, as defined {@link LambdaMetafactory above}.
337 * @throws NullPointerException If any argument is {@code null}.
338 */
339 public static CallSite metafactory(MethodHandles.Lookup caller,
340 String interfaceMethodName,
341 MethodType factoryType,
342 MethodType interfaceMethodType,
343 MethodHandle implementation,
344 MethodType dynamicMethodType)
345 throws LambdaConversionException {
346 AbstractValidatingLambdaMetafactory mf;
347 mf = new InnerClassLambdaMetafactory(Objects.requireNonNull(caller),
348 Objects.requireNonNull(factoryType),
349 Objects.requireNonNull(interfaceMethodName),
350 Objects.requireNonNull(interfaceMethodType),
351 Objects.requireNonNull(implementation),
352 Objects.requireNonNull(dynamicMethodType),
353 false,
354 EMPTY_CLASS_ARRAY,
355 EMPTY_MT_ARRAY);
356 mf.validateMetafactoryArgs();
357 return mf.buildCallSite();
358 }
359
360 /**
361 * Facilitates the creation of simple "function objects" that implement one
362 * or more interfaces by delegation to a provided {@link MethodHandle},
363 * after appropriate type adaptation and partial evaluation of arguments.
364 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
365 * call sites, to support the <em>lambda expression</em> and <em>method
366 * reference expression</em> features of the Java Programming Language.
367 *
368 * <p>This is the general, more flexible metafactory; a streamlined version
369 * is provided by {@link #metafactory(java.lang.invoke.MethodHandles.Lookup,
370 * String, MethodType, MethodType, MethodHandle, MethodType)}.
371 * A general description of the behavior of this method is provided
372 * {@link LambdaMetafactory above}.
373 *
374 * <p>The argument list for this method includes three fixed parameters,
375 * corresponding to the parameters automatically stacked by the VM for the
472 * instances of the interface named by {@code factoryType}
473 * @throws LambdaConversionException If {@code caller} does not have full privilege
474 * access, or if {@code interfaceMethodName} is not a valid JVM
475 * method name, or if the return type of {@code factoryType} is not
476 * an interface, or if any of {@code altInterfaces} is not an
477 * interface, or if {@code implementation} is not a direct method
478 * handle referencing a method or constructor, or if the linkage
479 * invariants are violated, as defined {@link LambdaMetafactory above}.
480 * @throws NullPointerException If any argument, or any component of {@code args},
481 * is {@code null}.
482 * @throws IllegalArgumentException If the number or types of the components
483 * of {@code args} do not follow the above rules, or if
484 * {@code altInterfaceCount} or {@code altMethodCount} are negative
485 * integers.
486 */
487 public static CallSite altMetafactory(MethodHandles.Lookup caller,
488 String interfaceMethodName,
489 MethodType factoryType,
490 Object... args)
491 throws LambdaConversionException {
492 Objects.requireNonNull(caller);
493 Objects.requireNonNull(interfaceMethodName);
494 Objects.requireNonNull(factoryType);
495 Objects.requireNonNull(args);
496 int argIndex = 0;
497 MethodType interfaceMethodType = extractArg(args, argIndex++, MethodType.class);
498 MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
499 MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
500 int flags = extractArg(args, argIndex++, Integer.class);
501 Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
502 MethodType[] altMethods = EMPTY_MT_ARRAY;
503 if ((flags & FLAG_MARKERS) != 0) {
504 int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
505 if (altInterfaceCount < 0) {
506 throw new IllegalArgumentException("negative argument count");
507 }
508 if (altInterfaceCount > 0) {
509 altInterfaces = extractArgs(args, argIndex, Class.class, altInterfaceCount);
510 argIndex += altInterfaceCount;
511 }
512 }
513 if ((flags & FLAG_BRIDGES) != 0) {
514 int altMethodCount = extractArg(args, argIndex++, Integer.class);
515 if (altMethodCount < 0) {
516 throw new IllegalArgumentException("negative argument count");
517 }
518 if (altMethodCount > 0) {
519 altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
520 argIndex += altMethodCount;
521 }
522 }
523 if (argIndex < args.length) {
524 throw new IllegalArgumentException("too many arguments");
525 }
526
527 boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
528 if (isSerializable) {
529 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(factoryType.returnType());
530 for (Class<?> c : altInterfaces)
531 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
532 if (!foundSerializableSupertype) {
533 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
534 altInterfaces[altInterfaces.length-1] = Serializable.class;
535 }
536 }
537
538 AbstractValidatingLambdaMetafactory mf
539 = new InnerClassLambdaMetafactory(caller,
540 factoryType,
541 interfaceMethodName,
542 interfaceMethodType,
543 implementation,
544 dynamicMethodType,
545 isSerializable,
546 altInterfaces,
547 altMethods);
548 mf.validateMetafactoryArgs();
549 return mf.buildCallSite();
550 }
551
552 private static <T> T extractArg(Object[] args, int index, Class<T> type) {
553 if (index >= args.length) {
554 throw new IllegalArgumentException("missing argument");
555 }
556 Object result = Objects.requireNonNull(args[index]);
557 if (!type.isInstance(result)) {
558 throw new IllegalArgumentException("argument has wrong type");
559 }
560 return type.cast(result);
561 }
562
563 private static <T> T[] extractArgs(Object[] args, int index, Class<T> type, int count) {
564 @SuppressWarnings("unchecked")
565 T[] result = (T[]) Array.newInstance(type, count);
566 for (int i = 0; i < count; i++) {
567 result[i] = extractArg(args, index + i, type);
|
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.io.Serializable;
29 import java.util.Arrays;
30 import java.lang.reflect.Array;
31 import java.util.Objects;
32
33 import jdk.internal.access.JavaLangInvokeAccess.ReflectableLambdaInfo;
34 import jdk.internal.vm.annotation.AOTSafeClassInitializer;
35
36 /**
37 * <p>Methods to facilitate the creation of simple "function objects" that
38 * implement one or more interfaces by delegation to a provided {@link MethodHandle},
39 * possibly after type adaptation and partial evaluation of arguments. These
40 * methods are typically used as <em>bootstrap methods</em> for {@code invokedynamic}
41 * call sites, to support the <em>lambda expression</em> and <em>method
42 * reference expression</em> features of the Java Programming Language.
43 *
44 * <p>Indirect access to the behavior specified by the provided {@code MethodHandle}
45 * proceeds in order through three phases:
46 * <ul>
47 * <li><p><em>Linkage</em> occurs when the methods in this class are invoked.
48 * They take as arguments an interface to be implemented (typically a
49 * <em>functional interface</em>, one with a single abstract method), a
50 * name and signature of a method from that interface to be implemented, a
51 * {@linkplain MethodHandleInfo direct method handle} describing the desired
52 * implementation behavior for that method, and possibly other additional
53 * metadata, and produce a {@link CallSite} whose target can be used to
327 * be enforced dynamically at invocation time.
328 * In simple use cases this is the same as
329 * {@code interfaceMethodType}.
330 * @return a CallSite whose target can be used to perform capture, generating
331 * instances of the interface named by {@code factoryType}
332 * @throws LambdaConversionException If {@code caller} does not have full privilege
333 * access, or if {@code interfaceMethodName} is not a valid JVM
334 * method name, or if the return type of {@code factoryType} is not
335 * an interface, or if {@code implementation} is not a direct method
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 return metafactoryInternal(caller, interfaceMethodName, factoryType, interfaceMethodType,
348 implementation, dynamicMethodType, null);
349 }
350
351 static CallSite metafactoryInternal(MethodHandles.Lookup caller,
352 String interfaceMethodName,
353 MethodType factoryType,
354 MethodType interfaceMethodType,
355 MethodHandle implementation,
356 MethodType dynamicMethodType,
357 ReflectableLambdaInfo reflectableLambdaInfo)
358 throws LambdaConversionException {
359 AbstractValidatingLambdaMetafactory mf = new InnerClassLambdaMetafactory(Objects.requireNonNull(caller),
360 Objects.requireNonNull(factoryType),
361 Objects.requireNonNull(interfaceMethodName),
362 Objects.requireNonNull(interfaceMethodType),
363 Objects.requireNonNull(implementation),
364 Objects.requireNonNull(dynamicMethodType),
365 false,
366 EMPTY_CLASS_ARRAY,
367 EMPTY_MT_ARRAY,
368 reflectableLambdaInfo);
369 mf.validateMetafactoryArgs();
370 return mf.buildCallSite();
371 }
372
373 /**
374 * Facilitates the creation of simple "function objects" that implement one
375 * or more interfaces by delegation to a provided {@link MethodHandle},
376 * after appropriate type adaptation and partial evaluation of arguments.
377 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
378 * call sites, to support the <em>lambda expression</em> and <em>method
379 * reference expression</em> features of the Java Programming Language.
380 *
381 * <p>This is the general, more flexible metafactory; a streamlined version
382 * is provided by {@link #metafactory(java.lang.invoke.MethodHandles.Lookup,
383 * String, MethodType, MethodType, MethodHandle, MethodType)}.
384 * A general description of the behavior of this method is provided
385 * {@link LambdaMetafactory above}.
386 *
387 * <p>The argument list for this method includes three fixed parameters,
388 * corresponding to the parameters automatically stacked by the VM for the
485 * instances of the interface named by {@code factoryType}
486 * @throws LambdaConversionException If {@code caller} does not have full privilege
487 * access, or if {@code interfaceMethodName} is not a valid JVM
488 * method name, or if the return type of {@code factoryType} is not
489 * an interface, or if any of {@code altInterfaces} is not an
490 * interface, or if {@code implementation} is not a direct method
491 * handle referencing a method or constructor, or if the linkage
492 * invariants are violated, as defined {@link LambdaMetafactory above}.
493 * @throws NullPointerException If any argument, or any component of {@code args},
494 * is {@code null}.
495 * @throws IllegalArgumentException If the number or types of the components
496 * of {@code args} do not follow the above rules, or if
497 * {@code altInterfaceCount} or {@code altMethodCount} are negative
498 * integers.
499 */
500 public static CallSite altMetafactory(MethodHandles.Lookup caller,
501 String interfaceMethodName,
502 MethodType factoryType,
503 Object... args)
504 throws LambdaConversionException {
505 return altMetafactoryInternal(caller, interfaceMethodName, factoryType, null, args);
506 }
507
508 static CallSite altMetafactoryInternal(MethodHandles.Lookup caller,
509 String interfaceMethodName,
510 MethodType factoryType,
511 ReflectableLambdaInfo reflectableLambdaInfo,
512 Object... args)
513 throws LambdaConversionException {
514 Objects.requireNonNull(caller);
515 Objects.requireNonNull(interfaceMethodName);
516 Objects.requireNonNull(factoryType);
517 Objects.requireNonNull(args);
518 int argIndex = 0;
519 MethodType interfaceMethodType = extractArg(args, argIndex++, MethodType.class);
520 MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
521 MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
522 int flags = extractArg(args, argIndex++, Integer.class);
523 Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
524 MethodType[] altMethods = EMPTY_MT_ARRAY;
525 if ((flags & FLAG_MARKERS) != 0) {
526 int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
527 if (altInterfaceCount < 0) {
528 throw new IllegalArgumentException("negative argument count");
529 }
530 if (altInterfaceCount > 0) {
531 altInterfaces = extractArgs(args, argIndex, Class.class, altInterfaceCount);
532 argIndex += altInterfaceCount;
533 }
534 }
535
536 if ((flags & FLAG_BRIDGES) != 0) {
537 int altMethodCount = extractArg(args, argIndex++, Integer.class);
538 if (altMethodCount < 0) {
539 throw new IllegalArgumentException("negative argument count");
540 }
541 if (altMethodCount > 0) {
542 altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
543 argIndex += altMethodCount;
544 }
545 }
546 if (argIndex < args.length) {
547 throw new IllegalArgumentException("too many arguments");
548 }
549
550 boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
551 if (isSerializable) {
552 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(factoryType.returnType());
553 for (Class<?> c : altInterfaces)
554 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
555 if (!foundSerializableSupertype) {
556 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
557 altInterfaces[altInterfaces.length-1] = Serializable.class;
558 }
559 }
560
561 AbstractValidatingLambdaMetafactory mf
562 = new InnerClassLambdaMetafactory(caller,
563 factoryType,
564 interfaceMethodName,
565 interfaceMethodType,
566 implementation,
567 dynamicMethodType,
568 isSerializable,
569 altInterfaces,
570 altMethods,
571 reflectableLambdaInfo);
572 mf.validateMetafactoryArgs();
573 return mf.buildCallSite();
574 }
575
576 private static <T> T extractArg(Object[] args, int index, Class<T> type) {
577 if (index >= args.length) {
578 throw new IllegalArgumentException("missing argument");
579 }
580 Object result = Objects.requireNonNull(args[index]);
581 if (!type.isInstance(result)) {
582 throw new IllegalArgumentException("argument has wrong type");
583 }
584 return type.cast(result);
585 }
586
587 private static <T> T[] extractArgs(Object[] args, int index, Class<T> type, int count) {
588 @SuppressWarnings("unchecked")
589 T[] result = (T[]) Array.newInstance(type, count);
590 for (int i = 0; i < count; i++) {
591 result[i] = extractArg(args, index + i, type);
|