diff a/src/java.base/share/classes/java/lang/invoke/VarHandles.java b/src/java.base/share/classes/java/lang/invoke/VarHandles.java
--- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java
@@ -57,13 +57,19 @@
     static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
         if (!f.isStatic()) {
             long foffset = MethodHandleNatives.objectFieldOffset(f);
             Class<?> type = f.getFieldType();
             if (!type.isPrimitive()) {
-                return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
-                       ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type)
-                       : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type));
+                if (f.isFlat()) {
+                    return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+                        ? new VarHandleValues.FieldInstanceReadOnly(refc, foffset, type, f.getCheckedFieldType())
+                        : new VarHandleValues.FieldInstanceReadWrite(refc, foffset, type, f.getCheckedFieldType()));
+                } else {
+                    return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.getCheckedFieldType())
+                       : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.getCheckedFieldType()));
+                }
             }
             else if (type == boolean.class) {
                 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
                        ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
                        : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
@@ -119,13 +125,19 @@
     static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
         Object base = MethodHandleNatives.staticFieldBase(f);
         long foffset = MethodHandleNatives.staticFieldOffset(f);
         Class<?> type = f.getFieldType();
         if (!type.isPrimitive()) {
-            return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
-                    ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type)
-                    : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type));
+            if (f.isFlat()) {
+                return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
+                        ? new VarHandleValues.FieldStaticReadOnly(decl, base, foffset, type, f.getCheckedFieldType())
+                        : new VarHandleValues.FieldStaticReadWrite(decl, base, foffset, type, f.getCheckedFieldType()));
+            } else {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                        ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.getCheckedFieldType())
+                        : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.getCheckedFieldType());
+            }
         }
         else if (type == boolean.class) {
             return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
                     ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
                     : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
@@ -209,11 +221,13 @@
         int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
         int ascale = UNSAFE.arrayIndexScale(arrayClass);
         int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
 
         if (!componentType.isPrimitive()) {
-            return maybeAdapt(new VarHandleReferences.Array(aoffset, ashift, arrayClass));
+            return maybeAdapt(UNSAFE.isFlatArray(arrayClass)
+                ? new VarHandleValues.Array(aoffset, ashift, arrayClass)
+                : new VarHandleReferences.Array(aoffset, ashift, arrayClass));
         }
         else if (componentType == boolean.class) {
             return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
         }
         else if (componentType == byte.class) {
