diff a/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
--- a/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
+++ b/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this
@@ -67,10 +67,17 @@
     final Class<?> implClass;                 // Class for referencing the implementation method "class CC"
     final MethodType dynamicMethodType;       // Dynamically checked method type "(Integer)Object"
     final boolean isSerializable;             // Should the returned instance be serializable
     final Class<?>[] altInterfaces;           // Additional interfaces to be implemented
     final MethodType[] altMethods;            // Signatures of additional methods to bridge
+    final MethodHandle quotableOpField;       // A getter method handle that is used to retrieve the
+                                              // string representation of the quotable lambda's associated
+                                              // intermediate representation (can be null).
+    final MethodHandleInfo quotableOpFieldInfo;  // Info about the quotable getter method handle (can be null).
+
+    final MethodType quotableOpType;          // The type of the quotable lambda's associated
+                                              // intermediate representation (can be null).
 
 
     /**
      * Meta-factory constructor.
      *
@@ -103,10 +110,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}.
@@ -117,11 +127,12 @@
                                         MethodType interfaceMethodType,
                                         MethodHandle implementation,
                                         MethodType dynamicMethodType,
                                         boolean isSerializable,
                                         Class<?>[] altInterfaces,
-                                        MethodType[] altMethods)
+                                        MethodType[] altMethods,
+                                        MethodHandle reflectiveField)
             throws LambdaConversionException {
         if (!caller.hasFullPrivilegeAccess()) {
             throw new LambdaConversionException(String.format(
                     "Invalid caller: %s",
                     caller.lookupClass().getName()));
@@ -178,10 +189,23 @@
 
         this.dynamicMethodType = dynamicMethodType;
         this.isSerializable = isSerializable;
         this.altInterfaces = altInterfaces;
         this.altMethods = altMethods;
+        this.quotableOpField = reflectiveField;
+        if (reflectiveField != null) {
+            // infer the method type associated with the intermediate representation of the
+            // quotable lambda. Since {@code factoryType} contains all the captured args
+            // we need to subtract the captured args that are required to invoke the lambda's
+            // bytecode. The type of {@code implementation} is useful here, as it corresponds to
+            // the signature of the emitted javac lambda implementation. From there, we need to
+            // drop all the dynamic arguments, which are obtained from {@code interfaceMethodType}.
+            this.quotableOpType = factoryType.dropParameterTypes(0,
+                    implementation.type().parameterCount() - interfaceMethodType.parameterCount());
+        } else {
+            quotableOpType = null;
+        }
 
         if (interfaceMethodName.isEmpty() ||
                 interfaceMethodName.indexOf('.') >= 0 ||
                 interfaceMethodName.indexOf(';') >= 0 ||
                 interfaceMethodName.indexOf('[') >= 0 ||
@@ -204,10 +228,24 @@
                 throw new LambdaConversionException(String.format(
                         "%s is not an interface",
                         c.getName()));
             }
         }
+
+        if (reflectiveField != null) {
+            try {
+                quotableOpFieldInfo = caller.revealDirect(reflectiveField); // may throw SecurityException
+            } catch (IllegalArgumentException e) {
+                throw new LambdaConversionException(implementation + " is not direct or cannot be cracked");
+            }
+            if (quotableOpFieldInfo.getReferenceKind() != REF_getField &&
+                    quotableOpFieldInfo.getReferenceKind() != REF_getStatic) {
+                throw new LambdaConversionException(String.format("Unsupported MethodHandle kind: %s", quotableOpFieldInfo));
+            }
+        } else {
+            quotableOpFieldInfo = null;
+        }
     }
 
     /**
      * Build the CallSite.
      *
@@ -223,11 +261,11 @@
      * @throws LambdaConversionException if there are improper conversions
      */
     void validateMetafactoryArgs() throws LambdaConversionException {
         // Check arity: captured + SAM == impl
         final int implArity = implMethodType.parameterCount();
-        final int capturedArity = factoryType.parameterCount();
+        final int capturedArity = factoryType.parameterCount() - reflectiveCaptureCount();
         final int samArity = interfaceMethodType.parameterCount();
         final int dynamicArity = dynamicMethodType.parameterCount();
         if (implArity != capturedArity + samArity) {
             throw new LambdaConversionException(
                     String.format("Incorrect number of parameters for %s method %s; %d captured parameters, %d functional interface method parameters, %d implementation parameters",
@@ -314,10 +352,14 @@
         for (MethodType bridgeMT : altMethods) {
             checkDescriptor(bridgeMT);
         }
     }
 
+    int reflectiveCaptureCount() {
+        return quotableOpType == null ? 0 : quotableOpType.parameterCount();
+    }
+
     /** Validate that the given descriptor's types are compatible with {@code dynamicMethodType} **/
     private void checkDescriptor(MethodType descriptor) throws LambdaConversionException {
         for (int i = 0; i < dynamicMethodType.parameterCount(); i++) {
             Class<?> dynamicParamType = dynamicMethodType.parameterType(i);
             Class<?> descriptorParamType = descriptor.parameterType(i);
