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 31 /** 32 * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p> 33 * 34 * <p>For every lambda expressions or method reference in the source code, there is a target type which is a 35 * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for 36 * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole 37 * method of the functional interface and the implementation method, and returns an object (the lambda object) that 38 * implements the target type. Methods of the lambda object invoke the implementation method. For method 39 * references, the implementation method is simply the referenced method; for lambda expressions, the 40 * implementation method is produced by the compiler based on the body of the lambda expression. The methods in 41 * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the 42 * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories. 43 * 44 * <p>The bootstrap methods in this class take the information about the functional interface, the implementation 45 * method, and the static types of the captured lambda arguments, and link a call site which, when invoked, 46 * produces the lambda object. 47 * 48 * <p>When parameterized types are used, the instantiated type of the functional interface method may be different 49 * from that in the functional interface. For example, consider 50 * {@code interface I<T> { int m(T x); }} if this functional interface type is used in a lambda 51 * {@code I<Byte>; v = ...}, we need both the actual functional interface method which has the signature 52 * {@code (Object)int} and the erased instantiated type of the functional interface method (or simply 53 * <I>instantiated method type</I>), which has signature 54 * {@code (Byte)int}. 55 * 56 * <p>The argument list of the implementation method and the argument list of the functional interface method(s) 57 * may differ in several ways. The implementation methods may have additional arguments to accommodate arguments 58 * captured by the lambda expression; there may also be differences resulting from permitted adaptations of 59 * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args, 60 * but this is expected to be handled by the compiler. 61 * 62 * <p>Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list. The 63 * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at 64 * invocation time. The bootstrap method has access to the entire static argument list (which in this case, 65 * contains method handles describing the implementation method and the canonical functional interface method), 66 * as well as a method signature describing the number and static types (but not the values) of the dynamic 67 * arguments, and the static return type of the invokedynamic site. 68 * 69 * <p>The implementation method is described with a method handle. In theory, any method handle could be used. 70 * Currently supported are method handles representing invocation of virtual, interface, constructor and static 71 * methods. 72 * 73 * <p>Assume: 74 * <ul> 75 * <li>the functional interface method has N arguments, of types (U1, U2, ... Un) and return type Ru</li> 125 * <td>Reference</td><td>Primitive</td> 126 * <td>strict: Q is a primitive wrapper and Primitive(Q) can be widened to S 127 * <br>loose: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S</td> 128 * <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types</td> 129 * </tr> 130 * <tr> 131 * <td>Reference</td><td>Reference</td> 132 * <td>strict: S is a supertype of Q 133 * <br>loose: none</td> 134 * <td>Cast from Q to S</td> 135 * </tr> 136 * </table> 137 * 138 * The default bootstrap ({@link #metaFactory}) represents the common cases and uses an optimized protocol. 139 * Alternate bootstraps (e.g., {@link #altMetaFactory}) exist to support uncommon cases such as serialization 140 * or additional marker superinterfaces. 141 * 142 */ 143 public class LambdaMetafactory { 144 145 /** Flag for alternate metafactories indicating the lambda object is 146 * must to be serializable */ 147 public static final int FLAG_SERIALIZABLE = 1 << 0; 148 149 /** 150 * Flag for alternate metafactories indicating the lambda object implements 151 * other marker interfaces 152 * besides Serializable 153 */ 154 public static final int FLAG_MARKERS = 1 << 1; 155 156 /** 157 * Flag for alternate metafactories indicating the lambda object requires 158 * additional bridge methods 159 */ 160 public static final int FLAG_BRIDGES = 1 << 2; 161 162 private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; 163 private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0]; 164 165 /** 166 * Standard meta-factory for conversion of lambda expressions or method 167 * references to functional interfaces. 168 * 169 * @param caller Stacked automatically by VM; represents a lookup context 170 * with the accessibility privileges of the caller. 171 * @param invokedName Stacked automatically by VM; the name of the invoked 172 * method as it appears at the call site. 173 * Currently unused. 174 * @param invokedType Stacked automatically by VM; the signature of the 175 * invoked method, which includes the expected static 176 * type of the returned lambda object, and the static 177 * types of the captured arguments for the lambda. 178 * In the event that the implementation method is an 179 * instance method, the first argument in the invocation 180 * signature will correspond to the receiver. 181 * @param samMethod The primary method in the functional interface to which 182 * the lambda or method reference is being converted, 183 * represented as a method handle. 184 * @param implMethod The implementation method which should be called 185 * (with suitable adaptation of argument types, return 186 * types, and adjustment for captured arguments) when 187 * methods of the resulting functional interface instance 188 * are invoked. 189 * @param instantiatedMethodType The signature of the primary functional 190 * interface method after type variables 191 * are substituted with their instantiation 192 * from the capture site 193 * @return a CallSite, which, when invoked, will return an instance of the 194 * functional interface 195 * @throws ReflectiveOperationException 196 * @throws LambdaConversionException If any of the meta-factory protocol 197 * invariants are violated 198 */ 199 public static CallSite metaFactory(MethodHandles.Lookup caller, 200 String invokedName, 201 MethodType invokedType, 202 MethodHandle samMethod, 203 MethodHandle implMethod, 204 MethodType instantiatedMethodType) 205 throws ReflectiveOperationException, LambdaConversionException { 206 AbstractValidatingLambdaMetafactory mf; 207 mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, 208 implMethod, instantiatedMethodType, 209 false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY); 210 mf.validateMetafactoryArgs(); 211 return mf.buildCallSite(); 212 } 213 214 /** 215 * Alternate meta-factory for conversion of lambda expressions or method 216 * references to functional interfaces, which supports serialization and 217 * other uncommon options. 218 * 219 * The declared argument list for this method is: 220 * 221 * CallSite altMetaFactory(MethodHandles.Lookup caller, 222 * String invokedName, 223 * MethodType invokedType, 224 * Object... args) 225 * 226 * but it behaves as if the argument list is: 227 * 228 * CallSite altMetaFactory(MethodHandles.Lookup caller, 229 * String invokedName, 230 * MethodType invokedType, 231 * MethodHandle samMethod 232 * MethodHandle implMethod, 233 * MethodType instantiatedMethodType, 234 * int flags, 235 * int markerInterfaceCount, // IF flags has MARKERS set 236 * Class... markerInterfaces // IF flags has MARKERS set 237 * int bridgeCount, // IF flags has BRIDGES set 238 * MethodType... bridges // IF flags has BRIDGES set 239 * ) 240 * 241 * 242 * @param caller Stacked automatically by VM; represents a lookup context 243 * with the accessibility privileges of the caller. 244 * @param invokedName Stacked automatically by VM; the name of the invoked 245 * method as it appears at the call site. Currently unused. 246 * @param invokedType Stacked automatically by VM; the signature of the 247 * invoked method, which includes the expected static 248 * type of the returned lambda object, and the static 249 * types of the captured arguments for the lambda. 250 * In the event that the implementation method is an 251 * instance method, the first argument in the invocation 252 * signature will correspond to the receiver. 253 * @param args flags and optional arguments, as described above 254 * @return a CallSite, which, when invoked, will return an instance of the 255 * functional interface 256 * @throws ReflectiveOperationException 257 * @throws LambdaConversionException If any of the meta-factory protocol 258 * invariants are violated 259 */ 260 public static CallSite altMetaFactory(MethodHandles.Lookup caller, 261 String invokedName, 262 MethodType invokedType, 263 Object... args) 264 throws ReflectiveOperationException, LambdaConversionException { 265 MethodHandle samMethod = (MethodHandle)args[0]; 266 MethodHandle implMethod = (MethodHandle)args[1]; 267 MethodType instantiatedMethodType = (MethodType)args[2]; 268 int flags = (Integer) args[3]; 269 Class<?>[] markerInterfaces; 270 MethodType[] bridges; 271 int argIndex = 4; 272 if ((flags & FLAG_MARKERS) != 0) { 273 int markerCount = (Integer) args[argIndex++]; 274 markerInterfaces = new Class<?>[markerCount]; 275 System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount); 276 argIndex += markerCount; 277 } 278 else 279 markerInterfaces = EMPTY_CLASS_ARRAY; 280 if ((flags & FLAG_BRIDGES) != 0) { 281 int bridgeCount = (Integer) args[argIndex++]; 282 bridges = new MethodType[bridgeCount]; 283 System.arraycopy(args, argIndex, bridges, 0, bridgeCount); 284 argIndex += bridgeCount; 285 } 286 else 287 bridges = EMPTY_MT_ARRAY; 288 289 boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType()); 290 for (Class<?> c : markerInterfaces) 291 foundSerializableSupertype |= Serializable.class.isAssignableFrom(c); 292 boolean isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0) 293 || foundSerializableSupertype; 294 295 if (isSerializable && !foundSerializableSupertype) { 296 markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1); 297 markerInterfaces[markerInterfaces.length-1] = Serializable.class; 298 } 299 300 AbstractValidatingLambdaMetafactory mf 301 = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, 302 implMethod, instantiatedMethodType, 303 isSerializable, markerInterfaces, bridges); 304 mf.validateMetafactoryArgs(); 305 return mf.buildCallSite(); 306 } 307 } | 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 /** 29 * <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p> 30 * 31 * <p>For every lambda expressions or method reference in the source code, there is a target type which is a 32 * functional interface. Evaluating a lambda expression produces an object of its target type. The mechanism for 33 * evaluating lambda expressions is to invoke an invokedynamic call site, which takes arguments describing the sole 34 * method of the functional interface and the implementation method, and returns an object (the lambda object) that 35 * implements the target type. Methods of the lambda object invoke the implementation method. For method 36 * references, the implementation method is simply the referenced method; for lambda expressions, the 37 * implementation method is produced by the compiler based on the body of the lambda expression. The methods in 38 * this file are the bootstrap methods for those invokedynamic call sites, called lambda factories, and the 39 * bootstrap methods responsible for linking the lambda factories are called lambda meta-factories. 40 * 41 * <p>The bootstrap methods in this class take the information about the functional interface, the implementation 42 * method, and the static types of the captured lambda arguments, and link a call site which, when invoked, 43 * produces the lambda object. 44 * 45 * <p>When parameterized types are used, the instantiated type of the functional interface method may be different 46 * from that in the functional interface. For example, consider 47 * <code>interface I<T> { int m(T x); }</code> if this functional interface type is used in a lambda 48 * <code>I<Byte> v = ...</code>, we need both the actual functional interface method which has the signature 49 * <code>(Object)int</code> and the erased instantiated type of the functional interface method (or simply 50 * <I>instantiated method type</I>), which has signature 51 * <code>(Byte)int</code>. 52 * 53 * <p>While functional interfaces only have a single abstract method from the language perspective (concrete 54 * methods in Object are and default methods may be present), at the bytecode level they may actually have multiple 55 * methods because of the need for bridge methods. Invoking any of these methods on the lambda object will result 56 * in invoking the implementation method. 57 * 58 * <p>The argument list of the implementation method and the argument list of the functional interface method(s) 59 * may differ in several ways. The implementation methods may have additional arguments to accommodate arguments 60 * captured by the lambda expression; there may also be differences resulting from permitted adaptations of 61 * arguments, such as casting, boxing, unboxing, and primitive widening. They may also differ because of var-args, 62 * but this is expected to be handled by the compiler. 63 * 64 * <p>Invokedynamic call sites have two argument lists: a static argument list and a dynamic argument list. The 65 * static argument list lives in the constant pool; the dynamic argument list lives on the operand stack at 66 * invocation time. The bootstrap method has access to the entire static argument list (which in this case, 67 * contains method handles describing the implementation method and the canonical functional interface method), 68 * as well as a method signature describing the number and static types (but not the values) of the dynamic 69 * arguments, and the static return type of the invokedynamic site. 70 * 71 * <p>The implementation method is described with a method handle. In theory, any method handle could be used. 72 * Currently supported are method handles representing invocation of virtual, interface, constructor and static 73 * methods. 74 * 75 * <p>Assume: 76 * <ul> 77 * <li>the functional interface method has N arguments, of types (U1, U2, ... Un) and return type Ru</li> 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 135 * <br>loose: none</td> 136 * <td>Cast from Q to S</td> 137 * </tr> 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 * 198 * The declared argument list for this method is: 199 * 200 * CallSite altMetaFactory(MethodHandles.Lookup caller, 201 * String invokedName, 202 * MethodType invokedType, 203 * Object... args) 204 * 205 * but it behaves as if the argument list is: 206 * 207 * CallSite altMetaFactory(MethodHandles.Lookup caller, 208 * String invokedName, 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 250 markerInterfaces = EMPTY_CLASS_ARRAY; 251 AbstractValidatingLambdaMetafactory mf; 252 mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType, 253 flags, markerInterfaces); 254 mf.validateMetafactoryArgs(); 255 return mf.buildCallSite(); 256 } 257 } |