< prev index next >

src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java

Print this page

  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);
< prev index next >