diff a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
--- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
+++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
@@ -36,16 +36,23 @@
 import java.lang.classfile.CodeBuilder;
 import java.lang.classfile.FieldBuilder;
 import java.lang.classfile.MethodBuilder;
 import java.lang.classfile.Opcode;
 import java.lang.classfile.TypeKind;
+import java.lang.classfile.constantpool.MethodHandleEntry;
+import java.lang.classfile.constantpool.NameAndTypeEntry;
 import java.lang.constant.ClassDesc;
 import java.lang.constant.DynamicConstantDesc;
 import java.lang.constant.MethodTypeDesc;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
 import java.lang.reflect.Modifier;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Optional;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.function.Consumer;
 
 import static java.lang.classfile.ClassFile.*;
 import java.lang.classfile.attribute.ExceptionsAttribute;
@@ -72,15 +79,26 @@
 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
     private static final String LAMBDA_INSTANCE_FIELD = "LAMBDA_INSTANCE$";
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
     private static final ClassDesc[] EMPTY_CLASSDESC_ARRAY = ConstantUtils.EMPTY_CLASSDESC;
 
+    // Static builders to avoid lambdas
+    record MethodBody(Consumer<CodeBuilder> code) implements Consumer<MethodBuilder> {
+        @Override
+        public void accept(MethodBuilder mb) {
+            mb.withCode(code);
+        }
+    };
+
     // For dumping generated classes to disk, for debugging purposes
     private static final ClassFileDumper lambdaProxyClassFileDumper;
 
     private static final boolean disableEagerInitialization;
 
+    private static final String NAME_METHOD_QUOTED = "quoted";
+    private static final String quotedInstanceFieldName = "quoted";
+
     static {
         // To dump the lambda proxy classes, set this system property:
         //    -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles
         // or -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true
         final String dumpProxyClassesKey = "jdk.invoke.LambdaMetafactory.dumpProxyClassFiles";
@@ -149,15 +167,16 @@
                                        MethodType interfaceMethodType,
                                        MethodHandle implementation,
                                        MethodType dynamicMethodType,
                                        boolean isSerializable,
                                        Class<?>[] altInterfaces,
-                                       MethodType[] altMethods)
+                                       MethodType[] altMethods,
+                                       MethodHandle reflectiveField)
             throws LambdaConversionException {
         super(caller, factoryType, interfaceMethodName, interfaceMethodType,
               implementation, dynamicMethodType,
-              isSerializable, altInterfaces, altMethods);
+              isSerializable, altInterfaces, altMethods, reflectiveField);
         implMethodClassDesc = implClassDesc(implClass);
         implMethodName = implInfo.getName();
         implMethodDesc = methodDesc(implInfo.getMethodType());
         constructorType = factoryType.changeReturnType(Void.TYPE);
         lambdaClassName = lambdaClassName(targetClass);
@@ -314,10 +333,15 @@
                 // Generate final fields to be filled in by constructor
                 for (int i = 0; i < argDescs.length; i++) {
                     clb.withField(argNames[i], argDescs[i], ACC_PRIVATE | ACC_FINAL);
                 }
 
+                // if quotable, generate the field that will hold the value of quoted
+                if (quotableOpGetter != null) {
+                    clb.withField(quotedInstanceFieldName, CodeReflectionSupport.CD_Quoted, ACC_PRIVATE + ACC_FINAL);
+                }
+
                 generateConstructor(clb);
 
                 if (factoryType.parameterCount() == 0 && disableEagerInitialization) {
                     generateClassInitializer(clb);
                 }
@@ -340,18 +364,29 @@
 
                 if (isSerializable)
                     generateSerializationFriendlyMethods(clb);
                 else if (finalAccidentallySerializable)
                     generateSerializationHostileMethods(clb);
+
+                if (quotableOpGetter != null) {
+                    generateQuotableMethod(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;
+            List<?> classdata;
+            if (useImplMethodHandle || quotableOpGetter != null) {
+                classdata = quotableOpGetter == null ?
+                        List.of(implementation) :
+                        List.of(implementation, quotableOpGetter, CodeReflectionSupport.HANDLE_MAKE_QUOTED);
+            } else {
+                classdata = null;
+            }
             return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, lambdaProxyClassFileDumper, NESTMATE_CLASS | STRONG_LOADER_LINK)
                          .defineClass(!disableEagerInitialization, classdata);
 
         } catch (Throwable t) {
             throw new InternalError(t);
@@ -397,15 +432,96 @@
                             cob.aload(0);
                             Class<?> argType = factoryType.parameterType(i);
                             cob.loadLocal(TypeKind.from(argType), cob.parameterSlot(i));
                             cob.putfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argNames[i], argDescs[i])));
                         }
+                        if (quotableOpGetter != null) {
+                            generateQuotedFieldInitializer(cob);
+                        }
                         cob.return_();
                     }
                 });
     }
 
+    private void generateQuotedFieldInitializer(CodeBuilder cob) {
+        ConstantPoolBuilder cp = cob.constantPool();
+        MethodHandleEntry bsmDataAt = cp.methodHandleEntry(BSM_CLASS_DATA_AT);
+        NameAndTypeEntry natMH = cp.nameAndTypeEntry(DEFAULT_NAME, CD_MethodHandle);
+        // push the receiver on the stack for operand of put field instruction
+        cob.aload(0)
+           .ldc(cp.constantDynamicEntry(cp.bsmEntry(bsmDataAt, List.of(cp.intEntry(2))), natMH))
+        // load op string from field
+           .ldc(cp.constantDynamicEntry(cp.bsmEntry(bsmDataAt, List.of(cp.intEntry(1))), natMH));
+        MethodType mtype = quotableOpGetterInfo.getMethodType();
+        if (quotableOpGetterInfo.getReferenceKind() != MethodHandleInfo.REF_invokeStatic) {
+            mtype = mtype.insertParameterTypes(0, implClass);
+        }
+        cob.invokevirtual(CD_MethodHandle, "invokeExact", mtype.describeConstable().get());
+
+        // load captured args in array
+
+        int capturedArity = factoryType.parameterCount();
+        cob.loadConstant(capturedArity)
+           .anewarray(CD_Object);
+        // initialize quoted captures
+        for (int i = 0; i < capturedArity; i++) {
+            cob.dup()
+               .loadConstant(i)
+               .aload(0)
+               .getfield(lambdaClassEntry.asSymbol(), argNames[i], argDescs[i]);
+            TypeConvertingMethodAdapter.boxIfTypePrimitive(cob, TypeKind.from(argDescs[i]));
+            cob.aastore();
+        }
+
+        // Create a Quoted from FuncOp and captured args Object[]
+
+        cob.invokevirtual(CD_MethodHandle, "invokeExact", methodDesc(CodeReflectionSupport.HANDLE_MAKE_QUOTED.type()))
+           .putfield(lambdaClassEntry.asSymbol(), quotedInstanceFieldName, CodeReflectionSupport.CD_Quoted);
+    }
+
+    static class CodeReflectionSupport {
+        static final Class<?> QUOTED_CLASS;
+        static final Class<?> QUOTABLE_CLASS;
+        static final MethodHandle HANDLE_MAKE_QUOTED;
+
+        static {
+            try {
+                ModuleLayer layer = codeLayer();
+                ClassLoader cl = layer.findLoader("jdk.incubator.code");
+                QUOTED_CLASS = cl.loadClass("jdk.incubator.code.Quoted");
+                QUOTABLE_CLASS = cl.loadClass("jdk.incubator.code.Quotable");
+                Class<?> quotedHelper = cl.loadClass("jdk.incubator.code.internal.QuotedHelper");
+                Class<?> funcOp = cl.loadClass("jdk.incubator.code.op.CoreOp$FuncOp");
+                MethodHandle makeQuoted = Lookup.IMPL_LOOKUP.findStatic(quotedHelper, "makeQuoted",
+                        MethodType.methodType(QUOTED_CLASS, MethodHandles.Lookup.class, funcOp, Object[].class));
+                HANDLE_MAKE_QUOTED = makeQuoted.bindTo(Lookup.IMPL_LOOKUP);
+            } catch (Throwable ex) {
+                throw new ExceptionInInitializerError(ex);
+            }
+        }
+
+        static ModuleLayer codeLayer() {
+            final ModuleLayer codeLayer;
+            if (ModuleLayer.boot().findModule("jdk.incubator.code").isPresent()) {
+                // we are in an exploded build, so just use the boot layer
+                return ModuleLayer.boot();
+            } else if (java.lang.module.ModuleFinder.ofSystem().find("jdk.incubator.code").isPresent()) {
+                // the code module is installed, but not in the boot layer, create a new layer which contains it
+                ModuleLayer parent = ModuleLayer.boot();
+                Configuration cf = parent.configuration()
+                        .resolve(ModuleFinder.of(), ModuleFinder.ofSystem(), Set.of("jdk.incubator.code"));
+                ClassLoader scl = ClassLoader.getSystemClassLoader();
+                return parent.defineModulesWithOneLoader(cf, scl);
+            } else {
+                throw new IllegalStateException("jdk.incubator.code module not found");
+            }
+        }
+
+        static final ClassDesc CD_Quoted = QUOTED_CLASS.describeConstable().get();
+        static final MethodTypeDesc MTD_Quoted = MethodTypeDescImpl.ofValidated(CD_Quoted);
+    }
+
     private static class SerializationSupport {
         // Serialization support
         private static final ClassDesc CD_SerializedLambda = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/SerializedLambda;");
         private static final ClassDesc CD_ObjectOutputStream = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectOutputStream;");
         private static final ClassDesc CD_ObjectInputStream = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectInputStream;");
@@ -458,10 +574,24 @@
                            .areturn();
                     }
                 });
     }
 
+    /**
+     * Generate a writeReplace method that supports serialization
+     */
+    private void generateQuotableMethod(ClassBuilder clb) {
+        clb.withMethod(NAME_METHOD_QUOTED, CodeReflectionSupport.MTD_Quoted, ACC_PUBLIC + ACC_FINAL, new MethodBody(new Consumer<CodeBuilder>() {
+            @Override
+            public void accept(CodeBuilder cob) {
+                cob.aload(0)
+                   .getfield(lambdaClassEntry.asSymbol(), quotedInstanceFieldName, CodeReflectionSupport.CD_Quoted)
+                   .areturn();
+            }
+        }));
+    }
+
     /**
      * Generate a readObject/writeObject method that is hostile to serialization
      */
     private void generateSerializationHostileMethods(ClassBuilder clb) {
         var hostileMethod = new Consumer<MethodBuilder>() {
@@ -501,14 +631,14 @@
                     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 < argNames.length; i++) {
+                for (int i = 0; i < argNames.length ; i++) {
                     cob.aload(0)
                        .getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argNames[i], argDescs[i])));
                 }
 
                 convertArgumentTypes(cob, methodType);
