1 /*
2 * Copyright (c) 2012, 2021, 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.io.Serializable;
29 import java.util.Arrays;
30 import java.lang.reflect.Array;
31 import java.util.Objects;
32
33 /**
34 * <p>Methods to facilitate the creation of simple "function objects" that
35 * implement one or more interfaces by delegation to a provided {@link MethodHandle},
36 * possibly after type adaptation and partial evaluation of arguments. These
37 * methods are typically used as <em>bootstrap methods</em> for {@code invokedynamic}
38 * call sites, to support the <em>lambda expression</em> and <em>method
39 * reference expression</em> features of the Java Programming Language.
40 *
41 * <p>Indirect access to the behavior specified by the provided {@code MethodHandle}
42 * proceeds in order through three phases:
43 * <ul>
44 * <li><p><em>Linkage</em> occurs when the methods in this class are invoked.
45 * They take as arguments an interface to be implemented (typically a
46 * <em>functional interface</em>, one with a single abstract method), a
47 * name and signature of a method from that interface to be implemented, a
234 public final class LambdaMetafactory {
235
236 private LambdaMetafactory() {}
237
238 /** Flag for {@link #altMetafactory} indicating the lambda object
239 * must be serializable */
240 public static final int FLAG_SERIALIZABLE = 1 << 0;
241
242 /**
243 * Flag for {@link #altMetafactory} indicating the lambda object implements
244 * other interfaces besides {@code Serializable}
245 */
246 public static final int FLAG_MARKERS = 1 << 1;
247
248 /**
249 * Flag for alternate metafactories indicating the lambda object requires
250 * additional methods that invoke the {@code implementation}
251 */
252 public static final int FLAG_BRIDGES = 1 << 2;
253
254 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
255 private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
256
257 // LambdaMetafactory bootstrap methods are startup sensitive, and may be
258 // special cased in java.lang.invoke.BootstrapMethodInvoker to ensure
259 // methods are invoked with exact type information to avoid generating
260 // code for runtime checks. Take care any changes or additions here are
261 // reflected there as appropriate.
262
263 /**
264 * Facilitates the creation of simple "function objects" that implement one
265 * or more interfaces by delegation to a provided {@link MethodHandle},
266 * after appropriate type adaptation and partial evaluation of arguments.
267 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
268 * call sites, to support the <em>lambda expression</em> and <em>method
269 * reference expression</em> features of the Java Programming Language.
270 *
271 * <p>This is the standard, streamlined metafactory; additional flexibility
272 * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
273 * A general description of the behavior of this method is provided
319 * @throws SecurityException If a security manager is present, and it
320 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
321 * from {@code caller} to the package of {@code implementation}.
322 */
323 public static CallSite metafactory(MethodHandles.Lookup caller,
324 String interfaceMethodName,
325 MethodType factoryType,
326 MethodType interfaceMethodType,
327 MethodHandle implementation,
328 MethodType dynamicMethodType)
329 throws LambdaConversionException {
330 AbstractValidatingLambdaMetafactory mf;
331 mf = new InnerClassLambdaMetafactory(Objects.requireNonNull(caller),
332 Objects.requireNonNull(factoryType),
333 Objects.requireNonNull(interfaceMethodName),
334 Objects.requireNonNull(interfaceMethodType),
335 Objects.requireNonNull(implementation),
336 Objects.requireNonNull(dynamicMethodType),
337 false,
338 EMPTY_CLASS_ARRAY,
339 EMPTY_MT_ARRAY);
340 mf.validateMetafactoryArgs();
341 return mf.buildCallSite();
342 }
343
344 /**
345 * Facilitates the creation of simple "function objects" that implement one
346 * or more interfaces by delegation to a provided {@link MethodHandle},
347 * after appropriate type adaptation and partial evaluation of arguments.
348 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
349 * call sites, to support the <em>lambda expression</em> and <em>method
350 * reference expression</em> features of the Java Programming Language.
351 *
352 * <p>This is the general, more flexible metafactory; a streamlined version
353 * is provided by {@link #metafactory(java.lang.invoke.MethodHandles.Lookup,
354 * String, MethodType, MethodType, MethodHandle, MethodType)}.
355 * A general description of the behavior of this method is provided
356 * {@link LambdaMetafactory above}.
357 *
358 * <p>The argument list for this method includes three fixed parameters,
359 * corresponding to the parameters automatically stacked by the VM for the
365 * CallSite altMetafactory(MethodHandles.Lookup caller,
366 * String interfaceMethodName,
367 * MethodType factoryType,
368 * Object... args)
369 * }</pre>
370 *
371 * <p>but it behaves as if the argument list is as follows:
372 *
373 * <pre>{@code
374 * CallSite altMetafactory(MethodHandles.Lookup caller,
375 * String interfaceMethodName,
376 * MethodType factoryType,
377 * MethodType interfaceMethodType,
378 * MethodHandle implementation,
379 * MethodType dynamicMethodType,
380 * int flags,
381 * int altInterfaceCount, // IF flags has MARKERS set
382 * Class... altInterfaces, // IF flags has MARKERS set
383 * int altMethodCount, // IF flags has BRIDGES set
384 * MethodType... altMethods // IF flags has BRIDGES set
385 * )
386 * }</pre>
387 *
388 * <p>Arguments that appear in the argument list for
389 * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
390 * have the same specification as in that method. The additional arguments
391 * are interpreted as follows:
392 * <ul>
393 * <li>{@code flags} indicates additional options; this is a bitwise
394 * OR of desired flags. Defined flags are {@link #FLAG_BRIDGES},
395 * {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
396 * <li>{@code altInterfaceCount} is the number of additional interfaces
397 * the function object should implement, and is present if and only if the
398 * {@code FLAG_MARKERS} flag is set.</li>
399 * <li>{@code altInterfaces} is a variable-length list of additional
400 * interfaces to implement, whose length equals {@code altInterfaceCount},
401 * and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
402 * <li>{@code altMethodCount} is the number of additional method signatures
403 * the function object should implement, and is present if and only if
404 * the {@code FLAG_BRIDGES} flag is set.</li>
405 * <li>{@code altMethods} is a variable-length list of additional
406 * methods signatures to implement, whose length equals {@code altMethodCount},
407 * and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
408 * </ul>
409 *
410 * <p>Each class named by {@code altInterfaces} is subject to the same
411 * restrictions as {@code Rd}, the return type of {@code factoryType},
412 * as described {@link LambdaMetafactory above}. Each {@code MethodType}
413 * named by {@code altMethods} is subject to the same restrictions as
414 * {@code interfaceMethodType}, as described {@link LambdaMetafactory above}.
415 *
416 * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
417 * will implement {@code Serializable}, and will have a {@code writeReplace}
418 * method that returns an appropriate {@link SerializedLambda}. The
419 * {@code caller} class must have an appropriate {@code $deserializeLambda$}
420 * method, as described in {@link SerializedLambda}.
421 *
422 * <p>When the target of the {@code CallSite} returned from this method is
423 * invoked, the resulting function objects are instances of a class with
424 * the following properties:
425 * <ul>
426 * <li>The class implements the interface named by the return type
427 * of {@code factoryType} and any interfaces named by {@code altInterfaces}</li>
428 * <li>The class declares methods with the name given by {@code interfaceMethodName},
429 * and the signature given by {@code interfaceMethodType} and additional signatures
430 * given by {@code altMethods}</li>
431 * <li>The class may override methods from {@code Object}, and may
432 * implement methods related to serialization.</li>
433 * </ul>
434 *
435 * @param caller Represents a lookup context with the accessibility
436 * privileges of the caller. Specifically, the lookup context
437 * must have {@linkplain MethodHandles.Lookup#hasFullPrivilegeAccess()
438 * full privilege access}.
439 * When used with {@code invokedynamic}, this is stacked
440 * automatically by the VM.
441 * @param interfaceMethodName The name of the method to implement. When used with
470 * @throws SecurityException If a security manager is present, and it
471 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
472 * from {@code caller} to the package of {@code implementation}.
473 */
474 public static CallSite altMetafactory(MethodHandles.Lookup caller,
475 String interfaceMethodName,
476 MethodType factoryType,
477 Object... args)
478 throws LambdaConversionException {
479 Objects.requireNonNull(caller);
480 Objects.requireNonNull(interfaceMethodName);
481 Objects.requireNonNull(factoryType);
482 Objects.requireNonNull(args);
483 int argIndex = 0;
484 MethodType interfaceMethodType = extractArg(args, argIndex++, MethodType.class);
485 MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
486 MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
487 int flags = extractArg(args, argIndex++, Integer.class);
488 Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
489 MethodType[] altMethods = EMPTY_MT_ARRAY;
490 if ((flags & FLAG_MARKERS) != 0) {
491 int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
492 if (altInterfaceCount < 0) {
493 throw new IllegalArgumentException("negative argument count");
494 }
495 if (altInterfaceCount > 0) {
496 altInterfaces = extractArgs(args, argIndex, Class.class, altInterfaceCount);
497 argIndex += altInterfaceCount;
498 }
499 }
500 if ((flags & FLAG_BRIDGES) != 0) {
501 int altMethodCount = extractArg(args, argIndex++, Integer.class);
502 if (altMethodCount < 0) {
503 throw new IllegalArgumentException("negative argument count");
504 }
505 if (altMethodCount > 0) {
506 altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
507 argIndex += altMethodCount;
508 }
509 }
510 if (argIndex < args.length) {
511 throw new IllegalArgumentException("too many arguments");
512 }
513
514 boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
515 if (isSerializable) {
516 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(factoryType.returnType());
517 for (Class<?> c : altInterfaces)
518 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
519 if (!foundSerializableSupertype) {
520 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
521 altInterfaces[altInterfaces.length-1] = Serializable.class;
522 }
523 }
524
525 AbstractValidatingLambdaMetafactory mf
526 = new InnerClassLambdaMetafactory(caller,
527 factoryType,
528 interfaceMethodName,
529 interfaceMethodType,
530 implementation,
531 dynamicMethodType,
532 isSerializable,
533 altInterfaces,
534 altMethods);
535 mf.validateMetafactoryArgs();
536 return mf.buildCallSite();
537 }
538
539 private static <T> T extractArg(Object[] args, int index, Class<T> type) {
540 if (index >= args.length) {
541 throw new IllegalArgumentException("missing argument");
542 }
543 Object result = Objects.requireNonNull(args[index]);
544 if (!type.isInstance(result)) {
545 throw new IllegalArgumentException("argument has wrong type");
546 }
547 return type.cast(result);
548 }
549
550 private static <T> T[] extractArgs(Object[] args, int index, Class<T> type, int count) {
551 @SuppressWarnings("unchecked")
552 T[] result = (T[]) Array.newInstance(type, count);
553 for (int i = 0; i < count; i++) {
554 result[i] = extractArg(args, index + i, type);
|
1 /*
2 * Copyright (c) 2012, 2024, 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.reflect.code.Quotable;
29
30 import java.io.Serializable;
31 import java.util.Arrays;
32 import java.lang.reflect.Array;
33 import java.util.Objects;
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
236 public final class LambdaMetafactory {
237
238 private LambdaMetafactory() {}
239
240 /** Flag for {@link #altMetafactory} indicating the lambda object
241 * must be serializable */
242 public static final int FLAG_SERIALIZABLE = 1 << 0;
243
244 /**
245 * Flag for {@link #altMetafactory} indicating the lambda object implements
246 * other interfaces besides {@code Serializable}
247 */
248 public static final int FLAG_MARKERS = 1 << 1;
249
250 /**
251 * Flag for alternate metafactories indicating the lambda object requires
252 * additional methods that invoke the {@code implementation}
253 */
254 public static final int FLAG_BRIDGES = 1 << 2;
255
256 /** Flag for {@link #altMetafactory} indicating the lambda object
257 * must be a {@code Quotable} object, inspectable using code reflection. */
258 public static final int FLAG_QUOTABLE = 1 << 3;
259
260 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
261 private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
262
263 // LambdaMetafactory bootstrap methods are startup sensitive, and may be
264 // special cased in java.lang.invoke.BootstrapMethodInvoker to ensure
265 // methods are invoked with exact type information to avoid generating
266 // code for runtime checks. Take care any changes or additions here are
267 // reflected there as appropriate.
268
269 /**
270 * Facilitates the creation of simple "function objects" that implement one
271 * or more interfaces by delegation to a provided {@link MethodHandle},
272 * after appropriate type adaptation and partial evaluation of arguments.
273 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
274 * call sites, to support the <em>lambda expression</em> and <em>method
275 * reference expression</em> features of the Java Programming Language.
276 *
277 * <p>This is the standard, streamlined metafactory; additional flexibility
278 * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
279 * A general description of the behavior of this method is provided
325 * @throws SecurityException If a security manager is present, and it
326 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
327 * from {@code caller} to the package of {@code implementation}.
328 */
329 public static CallSite metafactory(MethodHandles.Lookup caller,
330 String interfaceMethodName,
331 MethodType factoryType,
332 MethodType interfaceMethodType,
333 MethodHandle implementation,
334 MethodType dynamicMethodType)
335 throws LambdaConversionException {
336 AbstractValidatingLambdaMetafactory mf;
337 mf = new InnerClassLambdaMetafactory(Objects.requireNonNull(caller),
338 Objects.requireNonNull(factoryType),
339 Objects.requireNonNull(interfaceMethodName),
340 Objects.requireNonNull(interfaceMethodType),
341 Objects.requireNonNull(implementation),
342 Objects.requireNonNull(dynamicMethodType),
343 false,
344 EMPTY_CLASS_ARRAY,
345 EMPTY_MT_ARRAY,
346 null);
347 mf.validateMetafactoryArgs();
348 return mf.buildCallSite();
349 }
350
351 /**
352 * Facilitates the creation of simple "function objects" that implement one
353 * or more interfaces by delegation to a provided {@link MethodHandle},
354 * after appropriate type adaptation and partial evaluation of arguments.
355 * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
356 * call sites, to support the <em>lambda expression</em> and <em>method
357 * reference expression</em> features of the Java Programming Language.
358 *
359 * <p>This is the general, more flexible metafactory; a streamlined version
360 * is provided by {@link #metafactory(java.lang.invoke.MethodHandles.Lookup,
361 * String, MethodType, MethodType, MethodHandle, MethodType)}.
362 * A general description of the behavior of this method is provided
363 * {@link LambdaMetafactory above}.
364 *
365 * <p>The argument list for this method includes three fixed parameters,
366 * corresponding to the parameters automatically stacked by the VM for the
372 * CallSite altMetafactory(MethodHandles.Lookup caller,
373 * String interfaceMethodName,
374 * MethodType factoryType,
375 * Object... args)
376 * }</pre>
377 *
378 * <p>but it behaves as if the argument list is as follows:
379 *
380 * <pre>{@code
381 * CallSite altMetafactory(MethodHandles.Lookup caller,
382 * String interfaceMethodName,
383 * MethodType factoryType,
384 * MethodType interfaceMethodType,
385 * MethodHandle implementation,
386 * MethodType dynamicMethodType,
387 * int flags,
388 * int altInterfaceCount, // IF flags has MARKERS set
389 * Class... altInterfaces, // IF flags has MARKERS set
390 * int altMethodCount, // IF flags has BRIDGES set
391 * MethodType... altMethods // IF flags has BRIDGES set
392 * MethodType reflectType // IF flags has QUOTABLE set
393 * MethodHandle reflectField // IF flags has QUOTABLE set
394 * )
395 * }</pre>
396 *
397 * <p>Arguments that appear in the argument list for
398 * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
399 * have the same specification as in that method. The additional arguments
400 * are interpreted as follows:
401 * <ul>
402 * <li>{@code flags} indicates additional options; this is a bitwise
403 * OR of desired flags. Defined flags are {@link #FLAG_BRIDGES},
404 * {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
405 * <li>{@code altInterfaceCount} is the number of additional interfaces
406 * the function object should implement, and is present if and only if the
407 * {@code FLAG_MARKERS} flag is set.</li>
408 * <li>{@code altInterfaces} is a variable-length list of additional
409 * interfaces to implement, whose length equals {@code altInterfaceCount},
410 * and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
411 * <li>{@code altMethodCount} is the number of additional method signatures
412 * the function object should implement, and is present if and only if
413 * the {@code FLAG_BRIDGES} flag is set.</li>
414 * <li>{@code altMethods} is a variable-length list of additional
415 * methods signatures to implement, whose length equals {@code altMethodCount},
416 * and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
417 * <li>{@code quotableField} is a
418 * {@linkplain MethodHandles.Lookup#findGetter(Class, String, Class) getter} method handle
419 * that is used to retrieve the string representation of the quotable lambda's associated
420 * intermediate representation.</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 FLAG_QUOTABLE is set in {@code flags}, the function objects
436 * will implement {@code Quotable}.
437 *
438 * <p>When the target of the {@code CallSite} returned from this method is
439 * invoked, the resulting function objects are instances of a class with
440 * the following properties:
441 * <ul>
442 * <li>The class implements the interface named by the return type
443 * of {@code factoryType} and any interfaces named by {@code altInterfaces}</li>
444 * <li>The class declares methods with the name given by {@code interfaceMethodName},
445 * and the signature given by {@code interfaceMethodType} and additional signatures
446 * given by {@code altMethods}</li>
447 * <li>The class may override methods from {@code Object}, and may
448 * implement methods related to serialization.</li>
449 * </ul>
450 *
451 * @param caller Represents a lookup context with the accessibility
452 * privileges of the caller. Specifically, the lookup context
453 * must have {@linkplain MethodHandles.Lookup#hasFullPrivilegeAccess()
454 * full privilege access}.
455 * When used with {@code invokedynamic}, this is stacked
456 * automatically by the VM.
457 * @param interfaceMethodName The name of the method to implement. When used with
486 * @throws SecurityException If a security manager is present, and it
487 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
488 * from {@code caller} to the package of {@code implementation}.
489 */
490 public static CallSite altMetafactory(MethodHandles.Lookup caller,
491 String interfaceMethodName,
492 MethodType factoryType,
493 Object... args)
494 throws LambdaConversionException {
495 Objects.requireNonNull(caller);
496 Objects.requireNonNull(interfaceMethodName);
497 Objects.requireNonNull(factoryType);
498 Objects.requireNonNull(args);
499 int argIndex = 0;
500 MethodType interfaceMethodType = extractArg(args, argIndex++, MethodType.class);
501 MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
502 MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
503 int flags = extractArg(args, argIndex++, Integer.class);
504 Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
505 MethodType[] altMethods = EMPTY_MT_ARRAY;
506 MethodHandle quotableField = null;
507 if ((flags & FLAG_MARKERS) != 0) {
508 int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
509 if (altInterfaceCount < 0) {
510 throw new IllegalArgumentException("negative argument count");
511 }
512 if (altInterfaceCount > 0) {
513 altInterfaces = extractArgs(args, argIndex, Class.class, altInterfaceCount);
514 argIndex += altInterfaceCount;
515 }
516 }
517 if ((flags & FLAG_BRIDGES) != 0) {
518 int altMethodCount = extractArg(args, argIndex++, Integer.class);
519 if (altMethodCount < 0) {
520 throw new IllegalArgumentException("negative argument count");
521 }
522 if (altMethodCount > 0) {
523 altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
524 argIndex += altMethodCount;
525 }
526 }
527 if ((flags & FLAG_QUOTABLE) != 0) {
528 quotableField = extractArg(args, argIndex++, MethodHandle.class);
529 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
530 altInterfaces[altInterfaces.length-1] = Quotable.class;
531 }
532 if (argIndex < args.length) {
533 throw new IllegalArgumentException("too many arguments");
534 }
535
536 boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
537 if (isSerializable) {
538 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(factoryType.returnType());
539 for (Class<?> c : altInterfaces)
540 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
541 if (!foundSerializableSupertype) {
542 altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
543 altInterfaces[altInterfaces.length-1] = Serializable.class;
544 }
545 }
546
547 AbstractValidatingLambdaMetafactory mf
548 = new InnerClassLambdaMetafactory(caller,
549 factoryType,
550 interfaceMethodName,
551 interfaceMethodType,
552 implementation,
553 dynamicMethodType,
554 isSerializable,
555 altInterfaces,
556 altMethods,
557 quotableField);
558 mf.validateMetafactoryArgs();
559 return mf.buildCallSite();
560 }
561
562 private static <T> T extractArg(Object[] args, int index, Class<T> type) {
563 if (index >= args.length) {
564 throw new IllegalArgumentException("missing argument");
565 }
566 Object result = Objects.requireNonNull(args[index]);
567 if (!type.isInstance(result)) {
568 throw new IllegalArgumentException("argument has wrong type");
569 }
570 return type.cast(result);
571 }
572
573 private static <T> T[] extractArgs(Object[] args, int index, Class<T> type, int count) {
574 @SuppressWarnings("unchecked")
575 T[] result = (T[]) Array.newInstance(type, count);
576 for (int i = 0; i < count; i++) {
577 result[i] = extractArg(args, index + i, type);
|