< prev index next >

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

Print this page




 171             argNames = argDescs = EMPTY_STRING_ARRAY;
 172         }
 173     }
 174 
 175     /**
 176      * Build the CallSite. Generate a class file which implements the functional
 177      * interface, define the class, if there are no parameters create an instance
 178      * of the class which the CallSite will return, otherwise, generate handles
 179      * which will call the class' constructor.
 180      *
 181      * @return a CallSite, which, when invoked, will return an instance of the
 182      * functional interface
 183      * @throws ReflectiveOperationException
 184      * @throws LambdaConversionException If properly formed functional interface
 185      * is not found
 186      */
 187     @Override
 188     CallSite buildCallSite() throws LambdaConversionException {
 189         final Class<?> innerClass = spinInnerClass();
 190         if (invokedType.parameterCount() == 0) {
 191             final Constructor<?>[] ctrs = AccessController.doPrivileged(
 192                     new PrivilegedAction<>() {
 193                 @Override
 194                 public Constructor<?>[] run() {
 195                     Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
 196                     if (ctrs.length == 1) {
 197                         // The lambda implementing inner class constructor is private, set
 198                         // it accessible (by us) before creating the constant sole instance
 199                         ctrs[0].setAccessible(true);
 200                     }
 201                     return ctrs;
 202                 }
 203                     });
 204             if (ctrs.length != 1) {
 205                 throw new LambdaConversionException("Expected one lambda constructor for "
 206                         + innerClass.getCanonicalName() + ", got " + ctrs.length);
 207             }
 208 
 209             try {
 210                 Object inst = ctrs[0].newInstance();
 211                 return new ConstantCallSite(MethodHandles.constant(samBase, inst));
 212             }
 213             catch (ReflectiveOperationException e) {
 214                 throw new LambdaConversionException("Exception instantiating lambda object", e);
 215             }
 216         } else {
 217             try {
 218                 UNSAFE.ensureClassInitialized(innerClass);
 219                 return new ConstantCallSite(
 220                         MethodHandles.Lookup.IMPL_LOOKUP
 221                              .findStatic(innerClass, NAME_FACTORY, invokedType));
 222             }
 223             catch (ReflectiveOperationException e) {
 224                 throw new LambdaConversionException("Exception finding constructor", e);
 225             }
 226         }

















































 227     }
 228 
 229     /**
 230      * Generate a class file which implements the functional
 231      * interface, define and return the class.
 232      *
 233      * @implNote The class that is generated does not include signature
 234      * information for exceptions that may be present on the SAM method.
 235      * This is to reduce classfile size, and is harmless as checked exceptions
 236      * are erased anyway, no one will ever compile against this classfile,
 237      * and we make no guarantees about the reflective properties of lambda
 238      * objects.
 239      *
 240      * @return a Class which implements the functional interface
 241      * @throws LambdaConversionException If properly formed functional interface
 242      * is not found
 243      */
 244     private Class<?> spinInnerClass() throws LambdaConversionException {
 245         String[] interfaces;
 246         String samIntf = samBase.getName().replace('.', '/');




 171             argNames = argDescs = EMPTY_STRING_ARRAY;
 172         }
 173     }
 174 
 175     /**
 176      * Build the CallSite. Generate a class file which implements the functional
 177      * interface, define the class, if there are no parameters create an instance
 178      * of the class which the CallSite will return, otherwise, generate handles
 179      * which will call the class' constructor.
 180      *
 181      * @return a CallSite, which, when invoked, will return an instance of the
 182      * functional interface
 183      * @throws ReflectiveOperationException
 184      * @throws LambdaConversionException If properly formed functional interface
 185      * is not found
 186      */
 187     @Override
 188     CallSite buildCallSite() throws LambdaConversionException {
 189         final Class<?> innerClass = spinInnerClass();
 190         if (invokedType.parameterCount() == 0) {


















 191             try {
 192                 Object inst = getConstructor(innerClass).newInstance();
 193                 return new ConstantCallSite(MethodHandles.constant(samBase, inst));
 194             }
 195             catch (ReflectiveOperationException e) {
 196                 throw new LambdaConversionException("Exception instantiating lambda object", e);
 197             }
 198         } else {
 199             try {
 200                 UNSAFE.ensureClassInitialized(innerClass);
 201                 return new ConstantCallSite(
 202                         MethodHandles.Lookup.IMPL_LOOKUP
 203                              .findStatic(innerClass, NAME_FACTORY, invokedType));
 204             }
 205             catch (ReflectiveOperationException e) {
 206                 throw new LambdaConversionException("Exception finding constructor", e);
 207             }
 208         }
 209     }
 210 
 211     /**
 212      * Builds an instance of the functional interface directly.
 213      *
 214      * Generate a class file which implements the functional interface, define
 215      * the class, create an instance of the class.
 216      *
 217      * @return an instance of the functional interface
 218      * @throws ReflectiveOperationException
 219      * @throws LambdaConversionException If properly formed functional interface
 220      * is not found or if the functional interface expects parameters
 221      */
 222     @Override
 223     Object buildFunctionalInterfaceInstance() throws LambdaConversionException {
 224         if (invokedType.parameterCount() == 0) {
 225             final Class<?> innerClass = spinInnerClass();
 226             try {
 227                 return getConstructor(innerClass).newInstance();
 228             }
 229             catch (ReflectiveOperationException e) {
 230                 throw new LambdaConversionException("Exception instantiating lambda object", e);
 231             }
 232         } else {
 233             throw new LambdaConversionException("Building functional interface instances directly " +
 234                     "only supported when there are no parameters");
 235         }
 236     }
 237 
 238     private Constructor<?> getConstructor(Class<?> innerClass) throws LambdaConversionException {
 239         final Constructor<?>[] ctrs = AccessController.doPrivileged(
 240                 new PrivilegedAction<>() {
 241                     @Override
 242                     public Constructor<?>[] run() {
 243                         Constructor<?>[] ctrs1 = innerClass.getDeclaredConstructors();
 244                         if (ctrs1.length == 1) {
 245                             // The lambda implementing inner class constructor is private, set
 246                             // it accessible (by us) before creating the constant sole instance
 247                             ctrs1[0].setAccessible(true);
 248                         }
 249                         return ctrs1;
 250                     }
 251                 });
 252 
 253         if (ctrs.length != 1) {
 254             throw new LambdaConversionException("Expected one lambda constructor for "
 255                     + innerClass.getCanonicalName() + ", got " + ctrs.length);
 256         }
 257         return ctrs[0];
 258     }
 259 
 260     /**
 261      * Generate a class file which implements the functional
 262      * interface, define and return the class.
 263      *
 264      * @implNote The class that is generated does not include signature
 265      * information for exceptions that may be present on the SAM method.
 266      * This is to reduce classfile size, and is harmless as checked exceptions
 267      * are erased anyway, no one will ever compile against this classfile,
 268      * and we make no guarantees about the reflective properties of lambda
 269      * objects.
 270      *
 271      * @return a Class which implements the functional interface
 272      * @throws LambdaConversionException If properly formed functional interface
 273      * is not found
 274      */
 275     private Class<?> spinInnerClass() throws LambdaConversionException {
 276         String[] interfaces;
 277         String samIntf = samBase.getName().replace('.', '/');


< prev index next >