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
@@ -32,13 +32,17 @@
 import sun.invoke.util.VerifyAccess;
 import sun.security.action.GetBooleanAction;
 
 import java.io.Serializable;
 import java.lang.constant.ConstantDescs;
+import java.lang.reflect.code.op.CoreOp.FuncOp;
+import java.lang.reflect.code.Quoted;
+import java.lang.reflect.code.interpreter.Interpreter;
+import java.lang.reflect.code.parser.OpParser;
+import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Modifier;
-import java.util.LinkedHashSet;
-import java.util.Set;
+import java.util.*;
 
 import static java.lang.invoke.MethodHandleStatics.CLASSFILE_VERSION;
 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
 import static java.lang.invoke.MethodType.methodType;
@@ -60,14 +64,16 @@
     private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
     private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
     private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
     private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
     private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
+    private static final String DESCR_METHOD_QUOTED = "()Ljava/lang/reflect/code/Quoted;";
 
     private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
     private static final String NAME_METHOD_READ_OBJECT = "readObject";
     private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
+    private static final String NAME_METHOD_QUOTED = "quoted";
 
     private static final String DESCR_CLASS = "Ljava/lang/Class;";
     private static final String DESCR_STRING = "Ljava/lang/String;";
     private static final String DESCR_OBJECT = "Ljava/lang/Object;";
     private static final String DESCR_CTOR_SERIALIZED_LAMBDA
@@ -85,10 +91,21 @@
     private static final boolean disableEagerInitialization;
 
     // condy to load implMethod from class data
     private static final ConstantDynamic implMethodCondy;
 
+    // condy to load reflective field from class data
+    private static final ConstantDynamic reflectiveFieldCondy;
+
+    private static final ConstantDynamic makeQuotedMethodCondy;
+
+    private static final MethodHandle HANDLE_MAKE_QUOTED;
+
+    private static final String quotedInstanceFieldName = "quoted";
+    private static final String quotedInstanceFieldDesc = Quoted.class.descriptorString();
+
+
     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";
@@ -96,14 +113,24 @@
 
         final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization";
         disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey);
 
         // condy to load implMethod from class data
-        MethodType classDataMType = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class);
-        Handle classDataBsm = new Handle(H_INVOKESTATIC, Type.getInternalName(MethodHandles.class), "classData",
-                                         classDataMType.descriptorString(), false);
-        implMethodCondy = new ConstantDynamic(ConstantDescs.DEFAULT_NAME, MethodHandle.class.descriptorString(), classDataBsm);
+        MethodType classDataAtMType = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class, int.class);
+        Handle classDataBsm = new Handle(H_INVOKESTATIC, Type.getInternalName(MethodHandles.class), "classDataAt",
+                                         classDataAtMType.descriptorString(), false);
+        implMethodCondy = new ConstantDynamic(ConstantDescs.DEFAULT_NAME, MethodHandle.class.descriptorString(), classDataBsm, 0);
+        reflectiveFieldCondy = new ConstantDynamic(ConstantDescs.DEFAULT_NAME, MethodHandle.class.descriptorString(), classDataBsm, 1);
+        makeQuotedMethodCondy = new ConstantDynamic(ConstantDescs.DEFAULT_NAME, MethodHandle.class.descriptorString(), classDataBsm, 2);
+
+        try {
+            HANDLE_MAKE_QUOTED = MethodHandles.lookup().findStatic(
+                    InnerClassLambdaMetafactory.class, "makeQuoted",
+                    MethodType.methodType(Quoted.class, String.class, Object[].class));
+        } catch (Throwable ex) {
+            throw new AssertionError(ex);
+        }
     }
 
     // See context values in AbstractValidatingLambdaMetafactory
     private final String implMethodClassName;        // Name of type containing implementation "CC"
     private final String implMethodName;             // Name of implementation method "impl"
@@ -147,10 +174,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 reflectiveField a {@linkplain MethodHandles.Lookup#findGetter(Class, String, Class) getter}
+     *                   method handle that is used to retrieve the string representation of the
+     *                   quotable lambda's associated intermediate representation.
      * @throws LambdaConversionException If any of the meta-factory protocol
      *         invariants are violated
      * @throws SecurityException If a security manager is present, and it
      *         <a href="MethodHandles.Lookup.html#secmgr">denies access</a>
      *         from {@code caller} to the package of {@code implementation}.
@@ -161,15 +191,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);
         implMethodClassName = implClass.getName().replace('.', '/');
         implMethodName = implInfo.getName();
         implMethodDesc = implInfo.getMethodType().toMethodDescriptorString();
         constructorType = factoryType.changeReturnType(Void.TYPE);
         lambdaClassName = lambdaClassName(targetClass);
@@ -327,10 +358,18 @@
                                             argDescs[i],
                                             null, null);
             fv.visitEnd();
         }
 
+        // if quotable, generate the field that will hold the value of quoted
+        if (quotableOpField != null) {
+            cw.visitField(ACC_PRIVATE + ACC_FINAL,
+                          quotedInstanceFieldName,
+                          quotedInstanceFieldDesc,
+                          null, null);
+        }
+
         generateConstructor();
 
         if (factoryType.parameterCount() == 0 && disableEagerInitialization) {
             generateClassInitializer();
         }
@@ -352,18 +391,29 @@
         if (isSerializable)
             generateSerializationFriendlyMethods();
         else if (accidentallySerializable)
             generateSerializationHostileMethods();
 
+        if (quotableOpField != null) {
+            generateQuotableMethod();
+        }
+
         cw.visitEnd();
 
         // Define the generated class in this VM.
 
         final byte[] classBytes = cw.toByteArray();
         try {
             // this class is linked at the indy callsite; so define a hidden nestmate
-            var classdata = useImplMethodHandle? implementation : null;
+            List<?> classdata;
+            if (useImplMethodHandle || quotableOpField != null) {
+                classdata = quotableOpField == null ?
+                        List.of(implementation) :
+                        List.of(implementation, quotableOpField, HANDLE_MAKE_QUOTED);
+            } else {
+                classdata = null;
+            }
             return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, Set.of(NESTMATE, STRONG), lambdaProxyClassFileDumper)
                          .defineClass(!disableEagerInitialization, classdata);
 
         } catch (Throwable t) {
             throw new InternalError(t);
@@ -413,16 +463,62 @@
             Class<?> argType = factoryType.parameterType(i);
             ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
             lvIndex += getParameterSize(argType);
             ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
         }
+
+        if (quotableOpField != null) {
+            generateQuotedFieldInitializer(ctor);
+        }
+
         ctor.visitInsn(RETURN);
         // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
         ctor.visitMaxs(-1, -1);
         ctor.visitEnd();
     }
 
+    private void generateQuotedFieldInitializer(MethodVisitor ctor) {
+        ctor.visitCode();
+
+        // push the receiver on the stack for operand of put field instruction
+        ctor.visitVarInsn(ALOAD, 0);
+
+        ctor.visitLdcInsn(makeQuotedMethodCondy);
+
+        // load op string from field
+
+        ctor.visitLdcInsn(reflectiveFieldCondy);
+        MethodType mtype = quotableOpFieldInfo.getMethodType();
+        if (quotableOpFieldInfo.getReferenceKind() != MethodHandleInfo.REF_getStatic) {
+            mtype = mtype.insertParameterTypes(0, implClass);
+        }
+        ctor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
+                "invokeExact", mtype.descriptorString(), false);
+
+        // load captured args in array
+
+        ctor.visitLdcInsn(quotableOpType.parameterCount());
+        ctor.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
+        int capturedArity = factoryType.parameterCount() - reflectiveCaptureCount();
+        // initialize quoted captures
+        TypeConvertingMethodAdapter tcmv = new TypeConvertingMethodAdapter(ctor);
+        for (int i = 0; i < reflectiveCaptureCount(); i++) {
+            ctor.visitInsn(DUP);
+            ctor.visitIntInsn(BIPUSH, i); // is it possible that i can be greater than Byte.MAX_VALUE ?
+            ctor.visitVarInsn(ALOAD, 0);
+            ctor.visitFieldInsn(GETFIELD, lambdaClassName, argNames[capturedArity + i], argDescs[capturedArity + i]);
+            tcmv.boxIfTypePrimitive(Type.getType(argDescs[capturedArity + i]));
+            ctor.visitInsn(AASTORE);
+        }
+
+        // now create a Quoted from String and captured args Object[]
+
+        ctor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
+                "invokeExact", HANDLE_MAKE_QUOTED.type().toMethodDescriptorString(), false);
+        ctor.visitFieldInsn(PUTFIELD, lambdaClassName, quotedInstanceFieldName, quotedInstanceFieldDesc);
+    }
+
     /**
      * Generate a writeReplace method that supports serialization
      */
     private void generateSerializationFriendlyMethods() {
         TypeConvertingMethodAdapter mv
@@ -459,10 +555,27 @@
         // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
         mv.visitMaxs(-1, -1);
         mv.visitEnd();
     }
 
+    /**
+     * Generate a writeReplace method that supports serialization
+     */
+    private void generateQuotableMethod() {
+        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL,
+                                          NAME_METHOD_QUOTED, DESCR_METHOD_QUOTED,
+                                          null, null);
+
+        mv.visitVarInsn(ALOAD, 0);
+        mv.visitFieldInsn(GETFIELD, lambdaClassName, quotedInstanceFieldName, quotedInstanceFieldDesc);
+        mv.visitInsn(ARETURN);
+
+        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
+        mv.visitMaxs(-1, -1);
+        mv.visitEnd();
+    }
+
     /**
      * Generate a readObject/writeObject method that is hostile to serialization
      */
     private void generateSerializationHostileMethods() {
         MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
@@ -510,11 +623,11 @@
                 visitInsn(DUP);
             }
             if (useImplMethodHandle) {
                 visitLdcInsn(implMethodCondy);
             }
-            for (int i = 0; i < argNames.length; i++) {
+            for (int i = 0; i < argNames.length - reflectiveCaptureCount(); i++) {
                 visitVarInsn(ALOAD, 0);
                 visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
             }
 
             convertArgumentTypes(methodType);
@@ -545,11 +658,11 @@
         }
 
         private void convertArgumentTypes(MethodType samType) {
             int lvIndex = 0;
             int samParametersLength = samType.parameterCount();
-            int captureArity = factoryType.parameterCount();
+            int captureArity = factoryType.parameterCount() - reflectiveCaptureCount();
             for (int i = 0; i < samParametersLength; i++) {
                 Class<?> argType = samType.parameterType(i);
                 visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
                 lvIndex += getParameterSize(argType);
                 convertType(argType, implMethodType.parameterType(captureArity + i), dynamicMethodType.parameterType(i));
@@ -604,6 +717,10 @@
         } else {
             return 4;
         }
     }
 
+    private static Quoted makeQuoted(String opText, Object[] args) {
+        FuncOp op = (FuncOp)OpParser.fromStringOfFuncOp(opText);
+        return (Quoted)Interpreter.invoke(Lookup.IMPL_LOOKUP, op, args);
+    }
 }
