< prev index next >

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

Print this page
*** 42,19 ***
--- 42,21 ---
  import java.lang.reflect.Modifier;
  import java.util.LinkedHashSet;
  import java.util.List;
  import java.util.Set;
  import java.util.function.Consumer;
+ import java.util.function.Function;
  
  import static java.lang.classfile.ClassFile.*;
  import java.lang.classfile.attribute.ExceptionsAttribute;
  import java.lang.classfile.constantpool.ClassEntry;
  import java.lang.classfile.constantpool.ConstantPoolBuilder;
  
  import static java.lang.constant.ConstantDescs.*;
  import static java.lang.invoke.MethodHandleNatives.Constants.NESTMATE_CLASS;
  import static java.lang.invoke.MethodHandleNatives.Constants.STRONG_LOADER_LINK;
+ import java.util.ArrayList;
  import jdk.internal.constant.ConstantUtils;
  import jdk.internal.constant.MethodTypeDescImpl;
  import jdk.internal.vm.annotation.Stable;
  import sun.invoke.util.Wrapper;
  

*** 129,10 ***
--- 131,13 ---
       *                       types must extend {@code Serializable}.
       * @param altInterfaces Additional interfaces which the lambda object
       *                      should implement.
       * @param altMethods Method types for additional signatures to be
       *                   implemented by invoking the implementation method
+      * @param finisher Function called at the end of the lambda class build process
+      *                 that returns an additional object to append to the class data,
+      *                 may be (@code null}, may return {@code null}.
       * @throws LambdaConversionException If any of the meta-factory protocol
       *         invariants are violated
       */
      public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
                                         MethodType factoryType,

*** 140,15 ***
                                         MethodType interfaceMethodType,
                                         MethodHandle implementation,
                                         MethodType dynamicMethodType,
                                         boolean isSerializable,
                                         Class<?>[] altInterfaces,
!                                        MethodType[] altMethods)
              throws LambdaConversionException {
          super(caller, factoryType, interfaceMethodName, interfaceMethodType,
                implementation, dynamicMethodType,
!               isSerializable, altInterfaces, altMethods);
          implMethodClassDesc = implClassDesc(implClass);
          implMethodName = implInfo.getName();
          implMethodDesc = methodDesc(implInfo.getMethodType());
          constructorType = factoryType.changeReturnType(Void.TYPE);
          lambdaClassName = lambdaClassName(targetClass);
--- 145,16 ---
                                         MethodType interfaceMethodType,
                                         MethodHandle implementation,
                                         MethodType dynamicMethodType,
                                         boolean isSerializable,
                                         Class<?>[] altInterfaces,
!                                        MethodType[] altMethods,
+                                        Function<ClassBuilder, Object> finisher)
              throws LambdaConversionException {
          super(caller, factoryType, interfaceMethodName, interfaceMethodType,
                implementation, dynamicMethodType,
!               isSerializable, altInterfaces, altMethods, finisher);
          implMethodClassDesc = implClassDesc(implClass);
          implMethodName = implInfo.getName();
          implMethodDesc = methodDesc(implInfo.getMethodType());
          constructorType = factoryType.changeReturnType(Void.TYPE);
          lambdaClassName = lambdaClassName(targetClass);

*** 305,10 ***
--- 311,11 ---
                  accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(i);
              }
              interfaces = List.copyOf(itfs);
          }
          final boolean finalAccidentallySerializable = accidentallySerializable;
+         final Object[] additionalClassDataHolder = new Object[1];
          final byte[] classBytes = ClassFile.of().build(lambdaClassEntry, pool, new Consumer<ClassBuilder>() {
              @Override
              public void accept(ClassBuilder clb) {
                  clb.withFlags(ACC_SUPER | ACC_FINAL | ACC_SYNTHETIC)
                     .withInterfaceSymbols(interfaces);

*** 341,18 ***
  
                  if (isSerializable)
                      generateSerializationFriendlyMethods(clb);
                  else if (finalAccidentallySerializable)
                      generateSerializationHostileMethods(clb);
              }
          });
  
          // Define the generated class in this VM.
  
          try {
              // this class is linked at the indy callsite; so define a hidden nestmate
!             var classdata = useImplMethodHandle? implementation : null;
              return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, lambdaProxyClassFileDumper, NESTMATE_CLASS | STRONG_LOADER_LINK)
                           .defineClass(!disableEagerInitialization, classdata);
  
          } catch (Throwable t) {
              throw new InternalError(t);
--- 348,25 ---
  
                  if (isSerializable)
                      generateSerializationFriendlyMethods(clb);
                  else if (finalAccidentallySerializable)
                      generateSerializationHostileMethods(clb);
+ 
+                 if (finisher != null) {
+                     additionalClassDataHolder[0] = finisher.apply(clb);
+                 }
              }
          });
  
          // Define the generated class in this VM.
  
          try {
              // this class is linked at the indy callsite; so define a hidden nestmate
!             var additionalClassData = additionalClassDataHolder[0];
+             var classdata = additionalClassData == null
+                     ? useImplMethodHandle ? List.of(implementation) : null
+                     : useImplMethodHandle ? List.of(implementation, additionalClassData) : List.of(additionalClassData);
              return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, lambdaProxyClassFileDumper, NESTMATE_CLASS | STRONG_LOADER_LINK)
                           .defineClass(!disableEagerInitialization, classdata);
  
          } catch (Throwable t) {
              throw new InternalError(t);

*** 501,11 ***
                      cob.new_(implMethodClassDesc)
                         .dup();
                  }
                  if (useImplMethodHandle) {
                      ConstantPoolBuilder cp = cob.constantPool();
!                     cob.ldc(cp.constantDynamicEntry(cp.bsmEntry(cp.methodHandleEntry(BSM_CLASS_DATA), List.of()),
                                                      cp.nameAndTypeEntry(DEFAULT_NAME, CD_MethodHandle)));
                  }
                  for (int i = 0; i < argDescs.length; i++) {
                      cob.aload(0)
                         .getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argName(i), argDescs[i])));
--- 515,11 ---
                      cob.new_(implMethodClassDesc)
                         .dup();
                  }
                  if (useImplMethodHandle) {
                      ConstantPoolBuilder cp = cob.constantPool();
!                     cob.ldc(cp.constantDynamicEntry(cp.bsmEntry(cp.methodHandleEntry(BSM_CLASS_DATA_AT), List.of(cp.intEntry(0))),
                                                      cp.nameAndTypeEntry(DEFAULT_NAME, CD_MethodHandle)));
                  }
                  for (int i = 0; i < argDescs.length; i++) {
                      cob.aload(0)
                         .getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argName(i), argDescs[i])));
< prev index next >