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