diff a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
@@ -60,12 +60,14 @@
 import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.file.PathFileObject;
 import com.sun.tools.javac.jvm.ClassFile.Version;
 import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
 import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.resources.CompilerProperties;
 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
+import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
@@ -73,10 +75,11 @@
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 
 import com.sun.tools.javac.code.Scope.LookupKind;
 
+import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.ARRAY;
 import static com.sun.tools.javac.code.TypeTag.CLASS;
 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
 import static com.sun.tools.javac.jvm.ClassFile.*;
 import static com.sun.tools.javac.jvm.ClassFile.Version.*;
@@ -108,10 +111,14 @@
 
     /** Switch: allow modules.
      */
     boolean allowModules;
 
+    /** Switch: allow value classes.
+     */
+    boolean allowValueClasses;
+
     /** Switch: allow sealed
      */
     boolean allowSealedTypes;
 
     /** Switch: allow records
@@ -282,10 +289,12 @@
         verbose         = options.isSet(Option.VERBOSE);
 
         Source source = Source.instance(context);
         preview = Preview.instance(context);
         allowModules     = Feature.MODULES.allowedInSource(source);
+        allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
+                Feature.VALUE_CLASSES.allowedInSource(source);
         allowRecords = Feature.RECORDS.allowedInSource(source);
         allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
         warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
 
         saveParameterNames = options.isSet(PARAMETERS);
@@ -576,23 +585,25 @@
                 ClassSymbol t = enterClass(readName(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
 
                 try {
-                    return (outer == Type.noType) ?
-                            t.erasure(types) :
-                        new ClassType(outer, List.nil(), t);
+                    if (outer == Type.noType) {
+                        ClassType et = (ClassType) t.erasure(types);
+                        return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata());
+                    }
+                    return new ClassType(outer, List.nil(), t, List.nil());
                 } finally {
                     sbp = startSbp;
                 }
             }
 
             case '<':           // generic arguments
                 ClassSymbol t = enterClass(readName(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
-                outer = new ClassType(outer, sigToTypes('>'), t) {
+                outer = new ClassType(outer, sigToTypes('>'), t, List.nil()) {
                         boolean completed = false;
                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
                         public Type getEnclosingType() {
                             if (!completed) {
                                 completed = true;
@@ -651,11 +662,11 @@
                 //we have seen an enclosing non-generic class
                 if (outer != Type.noType) {
                     t = enterClass(readName(signatureBuffer,
                                                  startSbp,
                                                  sbp - startSbp));
-                    outer = new ClassType(outer, List.nil(), t);
+                    outer = new ClassType(outer, List.nil(), t, List.nil());
                 }
                 signatureBuffer[sbp++] = (byte)'$';
                 continue;
             case '/':
                 signatureBuffer[sbp++] = (byte)'.';
@@ -1509,10 +1520,16 @@
                 sym.flags_field |= PREVIEW_API;
                 setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
             } else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
                 Assert.check(sym.kind == TYP);
                 sym.flags_field |= VALUE_BASED;
+            } else if (proxy.type.tsym.flatName() == syms.migratedValueClassInternalType.tsym.flatName()) {
+                Assert.check(sym.kind == TYP);
+                sym.flags_field |= MIGRATED_VALUE_CLASS;
+                if (needsValueFlag(sym, sym.flags_field)) {
+                    sym.flags_field |= VALUE_CLASS;
+                }
             } else if (proxy.type.tsym.flatName() == syms.restrictedType.tsym.flatName()) {
                 Assert.check(sym.kind == MTH);
                 sym.flags_field |= RESTRICTED;
             } else {
                 if (proxy.type.tsym == syms.annotationTargetType.tsym) {
@@ -1525,10 +1542,15 @@
                 }  else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
                     sym.flags_field |= PREVIEW_API;
                     setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
                 }  else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
                     sym.flags_field |= VALUE_BASED;
+                }  else if (proxy.type.tsym == syms.migratedValueClassType.tsym && sym.kind == TYP) {
+                    sym.flags_field |= MIGRATED_VALUE_CLASS;
+                    if (needsValueFlag(sym, sym.flags_field)) {
+                        sym.flags_field |= VALUE_CLASS;
+                    }
                 }  else if (proxy.type.tsym == syms.restrictedType.tsym) {
                     Assert.check(sym.kind == MTH);
                     sym.flags_field |= RESTRICTED;
                 }
                 proxies.append(proxy);
@@ -2891,11 +2913,11 @@
         if (ct.getEnclosingType().hasTag(CLASS))
             enterTypevars(c.owner, ct.getEnclosingType());
 
         // read flags, or skip if this is an inner class
         long f = nextChar();
-        long flags = adjustClassFlags(f);
+        long flags = adjustClassFlags(c, f);
         if ((flags & MODULE) == 0) {
             if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
             // read own class name and check that it matches
             currentModule = c.packge().modle;
             ClassSymbol self = poolReader.getClass(nextChar());
@@ -2983,11 +3005,11 @@
             int outerIdx = nextChar();
             int nameIdx = nextChar();
             ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
             Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
             if (name == null) name = names.empty;
-            long flags = adjustClassFlags(nextChar());
+            long flags = adjustClassFlags(c, nextChar());
             if (outer != null) { // we have a member class
                 if (name == names.empty)
                     name = names.one;
                 ClassSymbol member = enterClass(name, outer);
                 if ((flags & STATIC) == 0) {
@@ -3125,10 +3147,15 @@
 /************************************************************************
  * Adjusting flags
  ***********************************************************************/
 
     long adjustFieldFlags(long flags) {
+        boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
+        if (allowValueClasses && previewClassFile && (flags & ACC_STRICT) != 0) {
+            flags &= ~ACC_STRICT;
+            flags |= STRICT;
+        }
         return flags;
     }
 
     long adjustMethodFlags(long flags) {
         if ((flags & ACC_BRIDGE) != 0) {
@@ -3140,16 +3167,37 @@
             flags |= VARARGS;
         }
         return flags;
     }
 
-    long adjustClassFlags(long flags) {
+    long adjustClassFlags(ClassSymbol c, long flags) {
         if ((flags & ACC_MODULE) != 0) {
             flags &= ~ACC_MODULE;
             flags |= MODULE;
         }
-        return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
+        if (((flags & ACC_IDENTITY) != 0 && !isMigratedValueClass(flags)) || (majorVersion < V67.major && (flags & INTERFACE) == 0)) {
+            flags |= IDENTITY_TYPE;
+        } else if (needsValueFlag(c, flags)) {
+            flags |= VALUE_CLASS;
+        }
+        flags &= ~ACC_IDENTITY; // ACC_IDENTITY and SYNCHRONIZED bits overloaded
+        return flags;
+    }
+
+    private boolean needsValueFlag(Symbol c, long flags) {
+        boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
+        if (allowValueClasses) {
+            if (previewClassFile && majorVersion >= V67.major && (flags & INTERFACE) == 0 ||
+                    majorVersion >= V67.major && isMigratedValueClass(flags)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isMigratedValueClass(long flags) {
+        return allowValueClasses && ((flags & MIGRATED_VALUE_CLASS) != 0);
     }
 
     /**
      * A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
      * The attribute is only the last component of the original filename, so is unlikely
