94 * <li>For i=1..K, Di = Ai</li>
95 * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
96 * </ul></li>
97 * <li>If the implementation method is an instance method:
98 * <ul>
99 * <li>K + N = M + 1</li>
100 * <li>D1 must be a subtype of the enclosing class for the implementation method</li>
101 * <li>For i=2..K, Di = Aj, where j=i-1</li>
102 * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k-1</li>
103 * </ul></li>
104 * <li>The return type Rt is void, or the return type Ra is not void and is adaptable to Rt</li>
105 * </ul>
106 *
107 * <p>Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
108 * the completely known instantiated return type is adapted to the implementation arguments. Because the
109 * instantiated type of the implementation method is not available, the adaptability of return types cannot be
110 * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
111 * done on return type, while a strict version is applied to arguments.
112 *
113 * <p>A type Q is considered adaptable to S as follows:
114 * <table>
115 * <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
116 * <tr>
117 * <td>Primitive</td><td>Primitive</td>
118 * <td>Q can be converted to S via a primitive widening conversion</td>
119 * <td>None</td>
120 * </tr>
121 * <tr>
122 * <td>Primitive</td><td>Reference</td>
123 * <td>S is a supertype of the Wrapper(Q)</td>
124 * <td>Cast from Wrapper(Q) to S</td>
125 * </tr>
126 * <tr>
127 * <td>Reference</td><td>Primitive</td>
128 * <td>strict: Q is a primitive wrapper and Primitive(Q) can be widened to S
129 * <br>loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S</td>
130 * <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types</td>
131 * </tr>
132 * <tr>
133 * <td>Reference</td><td>Reference</td>
134 * <td>strict: S is a supertype of Q
138 * </table>
139 *
140 * The default bootstrap ({@link #metaFactory}) represents the common cases and uses an optimized protocol.
141 * Alternate bootstraps (e.g., {@link #altMetaFactory}) exist to support uncommon cases such as serialization
142 * or additional marker superinterfaces.
143 *
144 */
145 public class LambdaMetafactory {
146
147 /** Flag for alternate metafactories indicating the lambda object is must to be serializable */
148 public static final int FLAG_SERIALIZABLE = 1 << 0;
149
150 /**
151 * Flag for alternate metafactories indicating the lambda object implements other marker interfaces
152 * besides Serializable
153 */
154 public static final int FLAG_MARKERS = 1 << 1;
155
156 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
157
158 /**
159 * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.
160 *
161 * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
162 * of the caller.
163 * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
164 * Currently unused.
165 * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
166 * expected static type of the returned lambda object, and the static types of the captured
167 * arguments for the lambda. In the event that the implementation method is an instance method,
168 * the first argument in the invocation signature will correspond to the receiver.
169 * @param samMethod The primary method in the functional interface to which the lambda or method reference is
170 * being converted, represented as a method handle.
171 * @param implMethod The implementation method which should be called (with suitable adaptation of argument
172 * types, return types, and adjustment for captured arguments) when methods of the resulting
173 * functional interface instance are invoked.
174 * @param instantiatedMethodType The signature of the primary functional interface method after type variables
175 * are substituted with their instantiation from the capture site
176 * @return a CallSite, which, when invoked, will return an instance of the functional interface
177 * @throws ReflectiveOperationException
178 * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
179 */
180 public static CallSite metaFactory(MethodHandles.Lookup caller,
181 String invokedName,
182 MethodType invokedType,
183 MethodHandle samMethod,
184 MethodHandle implMethod,
185 MethodType instantiatedMethodType)
186 throws ReflectiveOperationException, LambdaConversionException {
187 AbstractValidatingLambdaMetafactory mf;
188 mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
189 0, EMPTY_CLASS_ARRAY);
190 mf.validateMetafactoryArgs();
191 return mf.buildCallSite();
192 }
193
194 /**
195 * Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces,
196 * which supports serialization and other uncommon options.
197 *
209 * MethodType invokedType,
210 * MethodHandle samMethod
211 * MethodHandle implMethod,
212 * MethodType instantiatedMethodType,
213 * int flags,
214 * int markerInterfaceCount, // IF flags has MARKERS set
215 * Class... markerInterfaces // IF flags has MARKERS set
216 * )
217 *
218 *
219 * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
220 * of the caller.
221 * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
222 * Currently unused.
223 * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu
224 * expected static type of the returned lambda object, and the static types of the captured
225 * arguments for the lambda. In the event that the implementation method is an instance method,
226 * the first argument in the invocation signature will correspond to the receiver.
227 * @param args argument to pass, flags, marker interface count, and marker interfaces as described above
228 * @return a CallSite, which, when invoked, will return an instance of the functional interface
229 * @throws ReflectiveOperationException
230 * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
231 */
232 public static CallSite altMetaFactory(MethodHandles.Lookup caller,
233 String invokedName,
234 MethodType invokedType,
235 Object... args)
236 throws ReflectiveOperationException, LambdaConversionException {
237 MethodHandle samMethod = (MethodHandle)args[0];
238 MethodHandle implMethod = (MethodHandle)args[1];
239 MethodType instantiatedMethodType = (MethodType)args[2];
240 int flags = (Integer) args[3];
241 Class<?>[] markerInterfaces;
242 int argIndex = 4;
243 if ((flags & FLAG_MARKERS) != 0) {
244 int markerCount = (Integer) args[argIndex++];
245 markerInterfaces = new Class<?>[markerCount];
246 System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
247 argIndex += markerCount;
248 }
249 else
|
94 * <li>For i=1..K, Di = Ai</li>
95 * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
96 * </ul></li>
97 * <li>If the implementation method is an instance method:
98 * <ul>
99 * <li>K + N = M + 1</li>
100 * <li>D1 must be a subtype of the enclosing class for the implementation method</li>
101 * <li>For i=2..K, Di = Aj, where j=i-1</li>
102 * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k-1</li>
103 * </ul></li>
104 * <li>The return type Rt is void, or the return type Ra is not void and is adaptable to Rt</li>
105 * </ul>
106 *
107 * <p>Note that the potentially parameterized implementation return type provides the value for the SAM. Whereas
108 * the completely known instantiated return type is adapted to the implementation arguments. Because the
109 * instantiated type of the implementation method is not available, the adaptability of return types cannot be
110 * checked as precisely at link-time as the arguments can be checked. Thus a loose version of link-time checking is
111 * done on return type, while a strict version is applied to arguments.
112 *
113 * <p>A type Q is considered adaptable to S as follows:
114 * <table summary="adaptable types">
115 * <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
116 * <tr>
117 * <td>Primitive</td><td>Primitive</td>
118 * <td>Q can be converted to S via a primitive widening conversion</td>
119 * <td>None</td>
120 * </tr>
121 * <tr>
122 * <td>Primitive</td><td>Reference</td>
123 * <td>S is a supertype of the Wrapper(Q)</td>
124 * <td>Cast from Wrapper(Q) to S</td>
125 * </tr>
126 * <tr>
127 * <td>Reference</td><td>Primitive</td>
128 * <td>strict: Q is a primitive wrapper and Primitive(Q) can be widened to S
129 * <br>loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S</td>
130 * <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types</td>
131 * </tr>
132 * <tr>
133 * <td>Reference</td><td>Reference</td>
134 * <td>strict: S is a supertype of Q
138 * </table>
139 *
140 * The default bootstrap ({@link #metaFactory}) represents the common cases and uses an optimized protocol.
141 * Alternate bootstraps (e.g., {@link #altMetaFactory}) exist to support uncommon cases such as serialization
142 * or additional marker superinterfaces.
143 *
144 */
145 public class LambdaMetafactory {
146
147 /** Flag for alternate metafactories indicating the lambda object is must to be serializable */
148 public static final int FLAG_SERIALIZABLE = 1 << 0;
149
150 /**
151 * Flag for alternate metafactories indicating the lambda object implements other marker interfaces
152 * besides Serializable
153 */
154 public static final int FLAG_MARKERS = 1 << 1;
155
156 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
157
158 /**
159 * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.
160 *
161 * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
162 * of the caller.
163 * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
164 * Currently unused.
165 * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
166 * expected static type of the returned lambda object, and the static types of the captured
167 * arguments for the lambda. In the event that the implementation method is an instance method,
168 * the first argument in the invocation signature will correspond to the receiver.
169 * @param samMethod The primary method in the functional interface to which the lambda or method reference is
170 * being converted, represented as a method handle.
171 * @param implMethod The implementation method which should be called (with suitable adaptation of argument
172 * types, return types, and adjustment for captured arguments) when methods of the resulting
173 * functional interface instance are invoked.
174 * @param instantiatedMethodType The signature of the primary functional interface method after type variables
175 * are substituted with their instantiation from the capture site
176 * @return a CallSite, which, when invoked, will return an instance of the functional interface
177 * @throws ReflectiveOperationException if the caller is not able to reconstruct one of the method handles
178 * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
179 */
180 public static CallSite metaFactory(MethodHandles.Lookup caller,
181 String invokedName,
182 MethodType invokedType,
183 MethodHandle samMethod,
184 MethodHandle implMethod,
185 MethodType instantiatedMethodType)
186 throws ReflectiveOperationException, LambdaConversionException {
187 AbstractValidatingLambdaMetafactory mf;
188 mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType,
189 0, EMPTY_CLASS_ARRAY);
190 mf.validateMetafactoryArgs();
191 return mf.buildCallSite();
192 }
193
194 /**
195 * Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces,
196 * which supports serialization and other uncommon options.
197 *
209 * MethodType invokedType,
210 * MethodHandle samMethod
211 * MethodHandle implMethod,
212 * MethodType instantiatedMethodType,
213 * int flags,
214 * int markerInterfaceCount, // IF flags has MARKERS set
215 * Class... markerInterfaces // IF flags has MARKERS set
216 * )
217 *
218 *
219 * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
220 * of the caller.
221 * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
222 * Currently unused.
223 * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu
224 * expected static type of the returned lambda object, and the static types of the captured
225 * arguments for the lambda. In the event that the implementation method is an instance method,
226 * the first argument in the invocation signature will correspond to the receiver.
227 * @param args argument to pass, flags, marker interface count, and marker interfaces as described above
228 * @return a CallSite, which, when invoked, will return an instance of the functional interface
229 * @throws ReflectiveOperationException if the caller is not able to reconstruct one of the method handles
230 * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
231 */
232 public static CallSite altMetaFactory(MethodHandles.Lookup caller,
233 String invokedName,
234 MethodType invokedType,
235 Object... args)
236 throws ReflectiveOperationException, LambdaConversionException {
237 MethodHandle samMethod = (MethodHandle)args[0];
238 MethodHandle implMethod = (MethodHandle)args[1];
239 MethodType instantiatedMethodType = (MethodType)args[2];
240 int flags = (Integer) args[3];
241 Class<?>[] markerInterfaces;
242 int argIndex = 4;
243 if ((flags & FLAG_MARKERS) != 0) {
244 int markerCount = (Integer) args[argIndex++];
245 markerInterfaces = new Class<?>[markerCount];
246 System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
247 argIndex += markerCount;
248 }
249 else
|