diff a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
--- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
+++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
@@ -23,10 +23,13 @@
  * questions.
  */
 
 package java.lang.reflect;
 
+import jdk.internal.misc.PreviewFeatures;
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ByteVector;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Label;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
@@ -37,14 +40,16 @@
 import java.lang.invoke.MethodType;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.Set;
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
 /**
  * ProxyGenerator contains the code to generate a dynamic proxy class
@@ -453,11 +458,12 @@
     /**
      * Generate a class file for the proxy class.  This method drives the
      * class file generation process.
      */
     private byte[] generateClassFile() {
-        visit(CLASSFILE_VERSION, accessFlags, dotToSlash(className), null,
+        int version = CLASSFILE_VERSION | (PreviewFeatures.isEnabled() ? Opcodes.V_PREVIEW : 0);
+        visit(version, accessFlags, dotToSlash(className), null,
                 JLR_PROXY, typeNames(interfaces));
 
         /*
          * Add proxy methods for the hashCode, equals,
          * and toString methods of java.lang.Object.  This is done before
@@ -481,13 +487,19 @@
         }
 
         /*
          * For each set of proxy methods with the same signature,
          * verify that the methods' return types are compatible.
+         *
+         * Determine if any value classes to be preloaded.
          */
+        Set<Class<?>> preloadClasses = new HashSet<>();
         for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
             checkReturnTypes(sigmethods);
+            for (ProxyMethod pm : sigmethods) {
+                preloadClasses.addAll(pm.preloadClasses());
+            }
         }
 
         generateConstructor();
 
         for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
@@ -498,10 +510,13 @@
 
                 // Generate code for proxy method
                 pm.generateMethod(this, className);
             }
         }
+        if (preloadClasses.size() > 0) {
+            generatePreloadAttribute(preloadClasses);
+        }
 
         generateStaticInitializer();
         generateLookupAccessor();
         return toByteArray();
     }
@@ -679,10 +694,28 @@
         // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
         mv.visitMaxs(-1, -1);
         mv.visitEnd();
     }
 
+    private void generatePreloadAttribute(Set<Class<?>> preloadClasses) {
+        Attribute attr = new Attribute("Preload") {
+            @Override
+            protected ByteVector write(ClassWriter cw,
+                                       byte[] code,
+                                       int len,
+                                       int maxStack,
+                                       int maxLocals) {
+                ByteVector attr = new ByteVector();
+                attr.putShort(preloadClasses.size());
+                for (Class<?> c : preloadClasses) {
+                    attr.putShort(cw.newClass(Type.getInternalName(c)));
+                }
+                return attr;
+            }
+        };
+        visitAttribute(attr);
+    }
     /**
      * A ProxyMethod object represents a proxy method in the proxy class
      * being generated: a method whose implementation will encode and
      * dispatch invocations to the proxy instance's invocation handler.
      */
@@ -808,10 +841,31 @@
             // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
             mv.visitMaxs(-1, -1);
             mv.visitEnd();
         }
 
+        Set<Class<?>> preloadClasses() {
+            Set<Class<?>> preloadClasses = new HashSet<>();
+            for (Class<?> type : parameterTypes) {
+                if (requiresPreload(type)) {
+                    preloadClasses.add(type);
+                }
+            }
+            if (requiresPreload(returnType)) {
+                preloadClasses.add(returnType);
+            }
+            return preloadClasses;
+        }
+
+        boolean requiresPreload(Class<?> cls) {
+            Class<?> c = cls;
+            while (c.isArray()) {
+                c = c.getComponentType();
+            }
+            return c.isValue();
+        }
+
         /**
          * Generate code for wrapping an argument of the given type
          * whose value can be found at the specified local variable
          * index, in order for it to be passed (as an Object) to the
          * invocation handler's "invoke" method.
@@ -894,14 +948,16 @@
          * =============== Code Generation Utility Methods ===============
          */
 
         /**
          * Generate code to invoke the Class.forName with the name of the given
-         * class to get its Class object at runtime.  The code is written to
-         * the supplied stream.  Note that the code generated by this method
-         * may cause the checked ClassNotFoundException to be thrown. A class
-         * loader is anticipated at local variable index 0.
+         * class to get its Class object at runtime.  And also generate code
+         * to invoke Class::asValueType if the class is a primitive value type.
+         *
+         * The code is written to the supplied stream.  Note that the code generated
+         * by this method may caused the checked ClassNotFoundException to be thrown.
+         * A class loader is anticipated at local variable index 0.
          */
         private void codeClassForName(MethodVisitor mv, Class<?> cl) {
             mv.visitLdcInsn(cl.getName());
             mv.visitInsn(ICONST_0); // false
             mv.visitVarInsn(ALOAD, 0); // classLoader
