diff a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -758,10 +758,35 @@
             return (t.hasTag(TYPEVAR))
                                     ? diags.fragment(Fragments.TypeParameter(t))
                                     : t;
         }
 
+    void checkConstraintsOfValueClass(JCClassDecl tree, ClassSymbol c) {
+        DiagnosticPosition pos = tree.pos();
+        for (Type st : types.closure(c.type)) {
+            if (st == null || st.tsym == null || st.tsym.kind == ERR)
+                continue;
+            if  (st.tsym == syms.objectType.tsym || st.tsym == syms.recordType.tsym || st.isInterface())
+                continue;
+            if (!st.tsym.isAbstract()) {
+                if (c != st.tsym) {
+                    log.error(pos, Errors.ConcreteSupertypeForValueClass(c, st));
+                }
+                continue;
+            }
+            // dealing with an abstract value or value super class below.
+            for (Symbol s : st.tsym.members().getSymbols(NON_RECURSIVE)) {
+                if (s.kind == MTH) {
+                    if ((s.flags() & (SYNCHRONIZED | STATIC)) == SYNCHRONIZED) {
+                        log.error(pos, Errors.SuperClassMethodCannotBeSynchronized(s, c, st));
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
     /** Check that type is a valid qualifier for a constructor reference expression
      */
     Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
         t = checkClassOrArrayType(pos, t);
         if (t.hasTag(CLASS)) {
@@ -815,10 +840,32 @@
             return typeTagError(pos,
                                 diags.fragment(Fragments.TypeReqRef),
                                 t);
     }
 
+    /** Check that type is an identity type, i.e. not a value type.
+     *  When not discernible statically, give it the benefit of doubt
+     *  and defer to runtime.
+     *
+     *  @param pos           Position to be used for error reporting.
+     *  @param t             The type to be checked.
+     */
+    void checkIdentityType(DiagnosticPosition pos, Type t) {
+        if (t.hasTag(TYPEVAR)) {
+            t = types.skipTypeVars(t, false);
+        }
+        if (t.isIntersection()) {
+            IntersectionClassType ict = (IntersectionClassType)t;
+            for (Type component : ict.getExplicitComponents()) {
+                checkIdentityType(pos, component);
+            }
+            return;
+        }
+        if (t.isPrimitive() || (t.isValueClass() && !t.tsym.isAbstract()))
+            typeTagError(pos, diags.fragment(Fragments.TypeReqIdentity), t);
+    }
+
     /** Check that each type is a reference type, i.e. a class, interface or array type
      *  or a type variable.
      *  @param trees         Original trees, used for error reporting.
      *  @param types         The types to be checked.
      */
@@ -1205,12 +1252,17 @@
                 mask = ReceiverParamFlags;
             else if (sym.owner.kind != TYP)
                 mask = LocalVarFlags;
             else if ((sym.owner.flags_field & INTERFACE) != 0)
                 mask = implicit = InterfaceVarFlags;
-            else
-                mask = VarFlags;
+            else {
+                boolean isInstanceFieldOfValueClass = sym.owner.type.isValueClass() && (flags & STATIC) == 0;
+                mask = !isInstanceFieldOfValueClass ? VarFlags : ExtendedVarFlags;
+                if (isInstanceFieldOfValueClass) {
+                    implicit |= FINAL | STRICT;
+                }
+            }
             break;
         case MTH:
             if (sym.name == names.init) {
                 if ((sym.owner.flags_field & ENUM) != 0) {
                     // enum constructors cannot be declared public or
@@ -1232,13 +1284,16 @@
                     }
                 } else {
                     mask = implicit = InterfaceMethodFlags;
                 }
             } else if ((sym.owner.flags_field & RECORD) != 0) {
-                mask = RecordMethodFlags;
+                mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
+                        RecordMethodFlags & ~SYNCHRONIZED : RecordMethodFlags;
             } else {
-                mask = MethodFlags;
+                // value objects do not have an associated monitor/lock
+                mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
+                        MethodFlags & ~SYNCHRONIZED : MethodFlags;
             }
             if ((flags & STRICTFP) != 0) {
                 warnOnExplicitStrictfp(pos);
             }
             // Imply STRICTFP if owner has STRICTFP set.
@@ -1251,11 +1306,11 @@
                     (sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) {
                 boolean implicitlyStatic = !sym.isAnonymous() &&
                         ((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0);
                 boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic;
                 // local statics are allowed only if records are allowed too
-                mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? StaticLocalFlags : LocalClassFlags;
+                mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedStaticLocalClassFlags : ExtendedLocalClassFlags;
                 implicit = implicitlyStatic ? STATIC : implicit;
             } else if (sym.owner.kind == TYP) {
                 // statics in inner classes are allowed only if records are allowed too
                 mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags;
                 if (sym.owner.owner.kind == PCK ||
@@ -1270,13 +1325,17 @@
                 mask = ExtendedClassFlags;
             }
             // Interfaces are always ABSTRACT
             if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
 
+            if ((flags & (INTERFACE | VALUE_CLASS)) == 0) {
+                implicit |= IDENTITY_TYPE;
+            }
+
             if ((flags & ENUM) != 0) {
-                // enums can't be declared abstract, final, sealed or non-sealed
-                mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED);
+                // enums can't be declared abstract, final, sealed or non-sealed or value
+                mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED | VALUE_CLASS);
                 implicit |= implicitEnumFinalFlag(tree);
             }
             if ((flags & RECORD) != 0) {
                 // records can't be declared abstract
                 mask &= ~ABSTRACT;
@@ -1285,10 +1344,18 @@
             if ((flags & STRICTFP) != 0) {
                 warnOnExplicitStrictfp(pos);
             }
             // Imply STRICTFP if owner has STRICTFP set.
             implicit |= sym.owner.flags_field & STRICTFP;
+
+            // concrete value classes are implicitly final
+            if ((flags & (ABSTRACT | INTERFACE | VALUE_CLASS)) == VALUE_CLASS) {
+                implicit |= FINAL;
+            }
+
+            // TYPs can't be declared synchronized
+            mask &= ~SYNCHRONIZED;
             break;
         default:
             throw new AssertionError();
         }
         long illegal = flags & ExtendedStandardFlags & ~mask;
@@ -1315,19 +1382,23 @@
                  &&
                  checkDisjoint(pos, flags,
                                ABSTRACT | INTERFACE,
                                FINAL | NATIVE | SYNCHRONIZED)
                  &&
+                 checkDisjoint(pos, flags,
+                        INTERFACE,
+                        VALUE_CLASS)
+                 &&
                  checkDisjoint(pos, flags,
                                PUBLIC,
                                PRIVATE | PROTECTED)
                  &&
                  checkDisjoint(pos, flags,
                                PRIVATE,
                                PUBLIC | PROTECTED)
                  &&
-                 checkDisjoint(pos, flags,
+                 checkDisjoint(pos, (flags | implicit), // complain against volatile & implcitly final entities too.
                                FINAL,
                                VOLATILE)
                  &&
                  (sym.kind == TYP ||
                   checkDisjoint(pos, flags,
@@ -1339,11 +1410,20 @@
                  && checkDisjoint(pos, flags,
                                 SEALED,
                            FINAL | NON_SEALED)
                  && checkDisjoint(pos, flags,
                                 SEALED,
-                                ANNOTATION)) {
+                                ANNOTATION)
+                && checkDisjoint(pos, flags,
+                                VALUE_CLASS,
+                                ANNOTATION)
+                && checkDisjoint(pos, flags,
+                                VALUE_CLASS,
+                                NON_SEALED)
+                && checkDisjoint(pos, flags,
+                                VALUE_CLASS,
+                                INTERFACE) ) {
             // skip
         }
         return flags & (mask | ~ExtendedStandardFlags) | implicit;
     }
 
@@ -2584,10 +2664,25 @@
             for (List<Type> m = supertypes; m != l; m = m.tail)
                 if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
                     return;
         }
         checkCompatibleConcretes(pos, c);
+
+        boolean cIsValue = (c.tsym.flags() & VALUE_CLASS) != 0;
+        Type identitySuper = null, valueSuper = null;
+        for (Type t : types.closure(c)) {
+            if (t != c) {
+                if ((t.tsym.flags() & IDENTITY_TYPE) != 0 && (t.tsym.flags() & VALUE_BASED) == 0)
+                    identitySuper = t;
+                else if ((t.tsym.flags() & VALUE_CLASS) != 0)
+                    valueSuper = t;
+                if (cIsValue && identitySuper != null && identitySuper.tsym != syms.objectType.tsym) { // Object is special
+                    log.error(pos, Errors.ValueTypeHasIdentitySuperType(c, identitySuper));
+                    break;
+                }
+            }
+        }
     }
 
     /** Check that all non-override equivalent methods accessible from 'site'
      *  are mutually compatible (JLS 8.4.8/9.4.1).
      *
@@ -4058,13 +4153,16 @@
                 if (initCall != null) {
                     log.error(apply.pos(), Errors.RedundantSuperclassInit);
                     break;
                 }
 
+                // valhalla is using this feature so commenting this code for now so that the
+                // build doesn't depend on preview code
                 // If super()/this() isn't first, require "statements before super()" feature
-                if (!firstStatement)
+                /*if (!firstStatement) {
                     preview.checkSourceLevel(apply.pos(), Feature.SUPER_INIT);
+                }*/
 
                 // We found a legitimate super()/this() call; remember it
                 initCall = methodName;
             } while (false);
 
