< 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 +145,16 @@
                                         MethodType interfaceMethodType,
                                         MethodHandle implementation,
                                         MethodType dynamicMethodType,
                                         boolean isSerializable,
                                         Class<?>[] altInterfaces,
-                                        MethodType[] altMethods)
+                                        MethodType[] altMethods,
+                                        Function<ClassBuilder, Object> finisher)
              throws LambdaConversionException {
          super(caller, factoryType, interfaceMethodName, interfaceMethodType,
                implementation, dynamicMethodType,
-               isSerializable, altInterfaces, altMethods);
+               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 +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 classdata = useImplMethodHandle? implementation : null;
+             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 +515,11 @@
                      cob.new_(implMethodClassDesc)
                         .dup();
                  }
                  if (useImplMethodHandle) {
                      ConstantPoolBuilder cp = cob.constantPool();
-                     cob.ldc(cp.constantDynamicEntry(cp.bsmEntry(cp.methodHandleEntry(BSM_CLASS_DATA), List.of()),
+                     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 >