< prev index next > src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java
Print this page
/*
! * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
/*
! * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* Flag for alternate metafactories indicating the lambda object requires
* additional methods that invoke the {@code implementation}
*/
public static final int FLAG_BRIDGES = 1 << 2;
+ /** Flag for {@link #altMetafactory} indicating the lambda object
+ * must be a {@code Quotable} object, inspectable using code reflection. */
+ public static final int FLAG_QUOTABLE = 1 << 3;
+
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
// LambdaMetafactory bootstrap methods are startup sensitive, and may be
// special cased in java.lang.invoke.BootstrapMethodInvoker to ensure
Objects.requireNonNull(interfaceMethodType),
Objects.requireNonNull(implementation),
Objects.requireNonNull(dynamicMethodType),
false,
EMPTY_CLASS_ARRAY,
! EMPTY_MT_ARRAY);
mf.validateMetafactoryArgs();
return mf.buildCallSite();
}
/**
Objects.requireNonNull(interfaceMethodType),
Objects.requireNonNull(implementation),
Objects.requireNonNull(dynamicMethodType),
false,
EMPTY_CLASS_ARRAY,
! EMPTY_MT_ARRAY,
+ null);
mf.validateMetafactoryArgs();
return mf.buildCallSite();
}
/**
* int flags,
* int altInterfaceCount, // IF flags has MARKERS set
* Class... altInterfaces, // IF flags has MARKERS set
* int altMethodCount, // IF flags has BRIDGES set
* MethodType... altMethods // IF flags has BRIDGES set
+ * MethodHandle quotableField // IF flags has QUOTABLE set
* )
* }</pre>
*
* <p>Arguments that appear in the argument list for
* {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
* the function object should implement, and is present if and only if
* the {@code FLAG_BRIDGES} flag is set.</li>
* <li>{@code altMethods} is a variable-length list of additional
* methods signatures to implement, whose length equals {@code altMethodCount},
* and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
+ * <li>{@code quotableField} is a
+ * {@linkplain MethodHandles.Lookup#findGetter(Class, String, Class) getter} method handle
+ * that is used to retrieve the string representation of the quotable lambda's associated
+ * intermediate representation.</li>
* </ul>
*
* <p>Each class named by {@code altInterfaces} is subject to the same
* restrictions as {@code Rd}, the return type of {@code factoryType},
* as described {@link LambdaMetafactory above}. Each {@code MethodType}
* will implement {@code Serializable}, and will have a {@code writeReplace}
* method that returns an appropriate {@link SerializedLambda}. The
* {@code caller} class must have an appropriate {@code $deserializeLambda$}
* method, as described in {@link SerializedLambda}.
*
+ * <p>When FLAG_QUOTABLE is set in {@code flags}, the function objects
+ * will implement {@code Quotable}.
+ *
* <p>When the target of the {@code CallSite} returned from this method is
* invoked, the resulting function objects are instances of a class with
* the following properties:
* <ul>
* <li>The class implements the interface named by the return type
MethodHandle implementation = extractArg(args, argIndex++, MethodHandle.class);
MethodType dynamicMethodType = extractArg(args, argIndex++, MethodType.class);
int flags = extractArg(args, argIndex++, Integer.class);
Class<?>[] altInterfaces = EMPTY_CLASS_ARRAY;
MethodType[] altMethods = EMPTY_MT_ARRAY;
+ MethodHandle quotableField = null;
if ((flags & FLAG_MARKERS) != 0) {
int altInterfaceCount = extractArg(args, argIndex++, Integer.class);
if (altInterfaceCount < 0) {
throw new IllegalArgumentException("negative argument count");
}
if (altMethodCount > 0) {
altMethods = extractArgs(args, argIndex, MethodType.class, altMethodCount);
argIndex += altMethodCount;
}
}
+ if ((flags & FLAG_QUOTABLE) != 0) {
+ quotableField = extractArg(args, argIndex++, MethodHandle.class);
+ altInterfaces = Arrays.copyOf(altInterfaces, altInterfaces.length + 1);
+ altInterfaces[altInterfaces.length-1] = InnerClassLambdaMetafactory.CodeReflectionSupport.QUOTABLE_CLASS;
+ }
if (argIndex < args.length) {
throw new IllegalArgumentException("too many arguments");
}
boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
interfaceMethodType,
implementation,
dynamicMethodType,
isSerializable,
altInterfaces,
! altMethods);
mf.validateMetafactoryArgs();
return mf.buildCallSite();
}
private static <T> T extractArg(Object[] args, int index, Class<T> type) {
interfaceMethodType,
implementation,
dynamicMethodType,
isSerializable,
altInterfaces,
! altMethods,
+ quotableField);
mf.validateMetafactoryArgs();
return mf.buildCallSite();
}
private static <T> T extractArg(Object[] args, int index, Class<T> type) {
< prev index next >