diff a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp
--- a/src/hotspot/share/classfile/classFileParser.cpp
+++ b/src/hotspot/share/classfile/classFileParser.cpp
@@ -19,10 +19,12 @@
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  *
  */
+
+#include "oops/inlineKlass.hpp"
 #include "precompiled.hpp"
 #include "cds/cdsConfig.hpp"
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
@@ -49,10 +51,11 @@
 #include "memory/universe.hpp"
 #include "oops/annotations.hpp"
 #include "oops/constantPool.inline.hpp"
 #include "oops/fieldInfo.hpp"
 #include "oops/fieldStreams.inline.hpp"
+#include "oops/inlineKlass.inline.hpp"
 #include "oops/instanceKlass.inline.hpp"
 #include "oops/instanceMirrorKlass.hpp"
 #include "oops/klass.inline.hpp"
 #include "oops/klassVtable.hpp"
 #include "oops/metadata.hpp"
@@ -83,10 +86,11 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/ostream.hpp"
 #include "utilities/resourceHash.hpp"
+#include "utilities/stringUtils.hpp"
 #include "utilities/utf8.hpp"
 #if INCLUDE_CDS
 #include "classfile/systemDictionaryShared.hpp"
 #endif
 #if INCLUDE_JFR
@@ -147,10 +151,12 @@
 
 #define JAVA_21_VERSION                   65
 
 #define JAVA_22_VERSION                   66
 
+#define CONSTANT_CLASS_DESCRIPTORS        67
+
 #define JAVA_23_VERSION                   67
 
 void ClassFileParser::set_class_bad_constant_seen(short bad_constant) {
   assert((bad_constant == JVM_CONSTANT_Module ||
           bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION,
@@ -187,11 +193,11 @@
     // Each of the following case guarantees one more byte in the stream
     // for the following tag or the access_flags following constant pool,
     // so we don't need bounds-check for reading tag.
     const u1 tag = cfs->get_u1_fast();
     switch (tag) {
-      case JVM_CONSTANT_Class : {
+      case JVM_CONSTANT_Class: {
         cfs->guarantee_more(3, CHECK);  // name_index, tag/access_flags
         const u2 name_index = cfs->get_u2_fast();
         cp->klass_index_at_put(index, name_index);
         break;
       }
@@ -508,10 +514,13 @@
       case JVM_CONSTANT_ClassIndex: {
         const int class_index = cp->klass_index_at(index);
         check_property(valid_symbol_at(class_index),
           "Invalid constant pool index %u in class file %s",
           class_index, CHECK);
+
+        Symbol* const name = cp->symbol_at(class_index);
+        const unsigned int name_len = name->utf8_length();
         cp->unresolved_klass_at_put(index, class_index, num_klasses++);
         break;
       }
       case JVM_CONSTANT_StringIndex: {
         const int string_index = cp->string_index_at(index);
@@ -717,11 +726,11 @@
             if (name != vmSymbols::object_initializer_name()) {
               classfile_parse_error(
                 "Bad method name at constant pool index %u in class file %s",
                 name_ref_index, THREAD);
               return;
-            } else if (!Signature::is_void_method(signature)) { // must have void signature.
+            } else if (!Signature::is_void_method(signature)) {  // must have void signature.
               throwIllegalSignature("Method", name, signature, CHECK);
             }
           }
         }
         break;
@@ -737,19 +746,28 @@
             const int name_and_type_ref_index =
               cp->uncached_name_and_type_ref_index_at(ref_index);
             const int name_ref_index =
               cp->name_ref_index_at(name_and_type_ref_index);
             const Symbol* const name = cp->symbol_at(name_ref_index);
-            if (ref_kind == JVM_REF_newInvokeSpecial) {
-              if (name != vmSymbols::object_initializer_name()) {
+
+            if (name != vmSymbols::object_initializer_name()) { // !<init>
+              if (ref_kind == JVM_REF_newInvokeSpecial) {
                 classfile_parse_error(
                   "Bad constructor name at constant pool index %u in class file %s",
                     name_ref_index, THREAD);
                 return;
               }
-            } else {
-              if (name == vmSymbols::object_initializer_name()) {
+            } else { // <init>
+              // The allowed invocation mode of <init> depends on its signature.
+              // This test corresponds to verify_invoke_instructions in the verifier.
+              const int signature_ref_index =
+                cp->signature_ref_index_at(name_and_type_ref_index);
+              const Symbol* const signature = cp->symbol_at(signature_ref_index);
+              if (signature->is_void_method_signature()
+                  && ref_kind == JVM_REF_newInvokeSpecial) {
+                // OK, could be a constructor call
+              } else {
                 classfile_parse_error(
                   "Bad method name at constant pool index %u in class file %s",
                   name_ref_index, THREAD);
                 return;
               }
@@ -797,66 +815,49 @@
 using NameSigHashtable = ResourceHashtable<NameSigHash, int,
                                            NameSigHash::HASH_ROW_SIZE,
                                            AnyObj::RESOURCE_AREA, mtInternal,
                                            &NameSigHash::hash, &NameSigHash::equals>;
 
-// Side-effects: populates the _local_interfaces field
-void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
-                                       const int itfs_len,
-                                       ConstantPool* const cp,
+static void check_identity_and_value_modifiers(ClassFileParser* current, const InstanceKlass* super_type, TRAPS) {
+  assert(super_type != nullptr,"Method doesn't support null super type");
+  if (super_type->access_flags().is_identity_class() && !current->access_flags().is_identity_class()
+      && super_type->name() != vmSymbols::java_lang_Object()) {
+      THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                err_msg("Value type %s has an identity type as supertype",
+                current->class_name()->as_klass_external_name()));
+  }
+}
+
+void ClassFileParser::parse_interfaces(const ClassFileStream* stream,
+                                       int itfs_len,
+                                       ConstantPool* cp,
                                        bool* const has_nonstatic_concrete_methods,
+                                       // FIXME: lots of these functions
+                                       // declare their parameters as const,
+                                       // which adds only noise to the code.
+                                       // Remove the spurious const modifiers.
+                                       // Many are of the form "const int x"
+                                       // or "T* const x".
                                        TRAPS) {
   assert(stream != nullptr, "invariant");
   assert(cp != nullptr, "invariant");
   assert(has_nonstatic_concrete_methods != nullptr, "invariant");
 
   if (itfs_len == 0) {
     _local_interfaces = Universe::the_empty_instance_klass_array();
+
   } else {
     assert(itfs_len > 0, "only called for len>0");
-    _local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, nullptr, CHECK);
-
-    int index;
+    _local_interface_indexes = new GrowableArray<u2>(itfs_len);
+    int index = 0;
     for (index = 0; index < itfs_len; index++) {
       const u2 interface_index = stream->get_u2(CHECK);
-      Klass* interf;
       check_property(
         valid_klass_reference_at(interface_index),
         "Interface name has bad constant pool index %u in class file %s",
         interface_index, CHECK);
-      if (cp->tag_at(interface_index).is_klass()) {
-        interf = cp->resolved_klass_at(interface_index);
-      } else {
-        Symbol* const unresolved_klass  = cp->klass_name_at(interface_index);
-
-        // Don't need to check legal name because it's checked when parsing constant pool.
-        // But need to make sure it's not an array type.
-        guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY,
-                           "Bad interface name in class file %s", CHECK);
-
-        // Call resolve_super so class circularity is checked
-        interf = SystemDictionary::resolve_super_or_fail(
-                                                  _class_name,
-                                                  unresolved_klass,
-                                                  Handle(THREAD, _loader_data->class_loader()),
-                                                  _protection_domain,
-                                                  false,
-                                                  CHECK);
-      }
-
-      if (!interf->is_interface()) {
-        THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
-                  err_msg("class %s can not implement %s, because it is not an interface (%s)",
-                          _class_name->as_klass_external_name(),
-                          interf->external_name(),
-                          interf->class_in_module_of_loader()));
-      }
-
-      if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
-        *has_nonstatic_concrete_methods = true;
-      }
-      _local_interfaces->at_put(index, InstanceKlass::cast(interf));
+      _local_interface_indexes->at_put_grow(index, interface_index);
     }
 
     if (!_need_verify || itfs_len <= 1) {
       return;
     }
@@ -864,12 +865,11 @@
     // Check if there's any duplicates in interfaces
     ResourceMark rm(THREAD);
     // Set containing interface names
     ResourceHashtable<Symbol*, int>* interface_names = new ResourceHashtable<Symbol*, int>();
     for (index = 0; index < itfs_len; index++) {
-      const InstanceKlass* const k = _local_interfaces->at(index);
-      Symbol* interface_name = k->name();
+      Symbol* interface_name = cp->klass_name_at(_local_interface_indexes->at(index));
       // If no duplicates, add (name, nullptr) in hashtable interface_names.
       if (!interface_names->put(interface_name, 0)) {
         classfile_parse_error("Duplicate interface name \"%s\" in class file %s",
                                interface_name->as_C_string(), THREAD);
         return;
@@ -951,10 +951,13 @@
     _method_IntrinsicCandidate,
     _jdk_internal_vm_annotation_Contended,
     _field_Stable,
     _jdk_internal_vm_annotation_ReservedStackAccess,
     _jdk_internal_ValueBased,
+    _jdk_internal_ImplicitlyConstructible,
+    _jdk_internal_LooselyConsistentValue,
+    _jdk_internal_NullRestricted,
     _java_lang_Deprecated,
     _java_lang_Deprecated_for_removal,
     _annotation_LIMIT
   };
   const Location _location;
@@ -1376,15 +1379,17 @@
   STATIC_OOP,           // Oops
   STATIC_BYTE,          // Boolean, Byte, char
   STATIC_SHORT,         // shorts
   STATIC_WORD,          // ints
   STATIC_DOUBLE,        // aligned long or double
+  STATIC_INLINE,        // inline type field
   NONSTATIC_OOP,
   NONSTATIC_BYTE,
   NONSTATIC_SHORT,
   NONSTATIC_WORD,
   NONSTATIC_DOUBLE,
+  NONSTATIC_INLINE,
   MAX_FIELD_ALLOCATION_TYPE,
   BAD_ALLOCATION_TYPE = -1
 };
 
 static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {
@@ -1400,16 +1405,17 @@
   NONSTATIC_SHORT,     // T_SHORT       =  9,
   NONSTATIC_WORD,      // T_INT         = 10,
   NONSTATIC_DOUBLE,    // T_LONG        = 11,
   NONSTATIC_OOP,       // T_OBJECT      = 12,
   NONSTATIC_OOP,       // T_ARRAY       = 13,
-  BAD_ALLOCATION_TYPE, // T_VOID        = 14,
-  BAD_ALLOCATION_TYPE, // T_ADDRESS     = 15,
-  BAD_ALLOCATION_TYPE, // T_NARROWOOP   = 16,
-  BAD_ALLOCATION_TYPE, // T_METADATA    = 17,
-  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
-  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 19,
+  NONSTATIC_OOP,       // T_PRIMITIVE_OBJECT = 14,
+  BAD_ALLOCATION_TYPE, // T_VOID        = 15,
+  BAD_ALLOCATION_TYPE, // T_ADDRESS     = 16,
+  BAD_ALLOCATION_TYPE, // T_NARROWOOP   = 17,
+  BAD_ALLOCATION_TYPE, // T_METADATA    = 18,
+  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 19,
+  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 20,
   BAD_ALLOCATION_TYPE, // 0
   BAD_ALLOCATION_TYPE, // 1
   BAD_ALLOCATION_TYPE, // 2
   BAD_ALLOCATION_TYPE, // 3
   STATIC_BYTE ,        // T_BOOLEAN     =  4,
@@ -1420,22 +1426,26 @@
   STATIC_SHORT,        // T_SHORT       =  9,
   STATIC_WORD,         // T_INT         = 10,
   STATIC_DOUBLE,       // T_LONG        = 11,
   STATIC_OOP,          // T_OBJECT      = 12,
   STATIC_OOP,          // T_ARRAY       = 13,
-  BAD_ALLOCATION_TYPE, // T_VOID        = 14,
-  BAD_ALLOCATION_TYPE, // T_ADDRESS     = 15,
-  BAD_ALLOCATION_TYPE, // T_NARROWOOP   = 16,
-  BAD_ALLOCATION_TYPE, // T_METADATA    = 17,
-  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
-  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 19,
+  STATIC_OOP,          // T_PRIMITIVE_OBJECT = 14,
+  BAD_ALLOCATION_TYPE, // T_VOID        = 15,
+  BAD_ALLOCATION_TYPE, // T_ADDRESS     = 16,
+  BAD_ALLOCATION_TYPE, // T_NARROWOOP   = 17,
+  BAD_ALLOCATION_TYPE, // T_METADATA    = 18,
+  BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 19,
+  BAD_ALLOCATION_TYPE, // T_CONFLICT    = 20
 };
 
-static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) {
+static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type, bool is_inline_type) {
   assert(type >= T_BOOLEAN && type < T_VOID, "only allowable values");
   FieldAllocationType result = _basic_type_to_atype[type + (is_static ? (T_CONFLICT + 1) : 0)];
   assert(result != BAD_ALLOCATION_TYPE, "bad type");
+  if (is_inline_type) {
+    result = is_static ? STATIC_INLINE : NONSTATIC_INLINE;
+  }
   return result;
 }
 
 class ClassFileParser::FieldAllocationCount : public ResourceObj {
  public:
@@ -1445,12 +1455,12 @@
     for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) {
       count[i] = 0;
     }
   }
 
-  void update(bool is_static, BasicType type) {
-    FieldAllocationType atype = basic_type_to_atype(is_static, type);
+  void update(bool is_static, BasicType type, bool is_inline_type) {
+    FieldAllocationType atype = basic_type_to_atype(is_static, type, is_inline_type);
     if (atype != BAD_ALLOCATION_TYPE) {
       // Make sure there is no overflow with injected fields.
       assert(count[atype] < 0xFFFF, "More than 65535 fields");
       count[atype]++;
     }
@@ -1458,11 +1468,11 @@
 };
 
 // Side-effects: populates the _fields, _fields_annotations,
 // _fields_type_annotations fields
 void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
-                                   bool is_interface,
+                                   AccessFlags class_access_flags,
                                    FieldAllocationCount* const fac,
                                    ConstantPool* cp,
                                    const int cp_size,
                                    u2* const java_fields_count_ptr,
                                    TRAPS) {
@@ -1473,31 +1483,42 @@
   assert(java_fields_count_ptr != nullptr, "invariant");
 
   assert(nullptr == _fields_annotations, "invariant");
   assert(nullptr == _fields_type_annotations, "invariant");
 
+  bool is_inline_type = !class_access_flags.is_identity_class() && !class_access_flags.is_abstract();
   cfs->guarantee_more(2, CHECK);  // length
   const u2 length = cfs->get_u2_fast();
   *java_fields_count_ptr = length;
 
   int num_injected = 0;
   const InjectedField* const injected = JavaClasses::get_injected(_class_name,
                                                                   &num_injected);
-  const int total_fields = length + num_injected;
+
+  // two more slots are required for inline classes:
+  // one for the static field with a reference to the pre-allocated default value
+  // one for the field the JVM injects when detecting an empty inline class
+  const int total_fields = length + num_injected + (is_inline_type ? 2 : 0);
 
   // Allocate a temporary resource array to collect field data.
   // After parsing all fields, data are stored in a UNSIGNED5 compressed stream.
   _temp_field_info = new GrowableArray<FieldInfo>(total_fields);
 
+  int instance_fields_count = 0;
   ResourceMark rm(THREAD);
   for (int n = 0; n < length; n++) {
     // access_flags, name_index, descriptor_index, attributes_count
     cfs->guarantee_more(8, CHECK);
 
+    jint recognized_modifiers = JVM_RECOGNIZED_FIELD_MODIFIERS;
+    if (!supports_inline_types()) {
+      recognized_modifiers &= ~JVM_ACC_STRICT;
+    }
+
+    const jint flags = cfs->get_u2_fast() & recognized_modifiers;
+    verify_legal_field_modifiers(flags, class_access_flags, CHECK);
     AccessFlags access_flags;
-    const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;
-    verify_legal_field_modifiers(flags, is_interface, CHECK);
     access_flags.set_flags(flags);
     FieldInfo::FieldFlags fieldFlags(0);
 
     const u2 name_index = cfs->get_u2_fast();
     check_property(valid_symbol_at(name_index),
@@ -1510,17 +1531,20 @@
     check_property(valid_symbol_at(signature_index),
       "Invalid constant pool index %u for field signature in class file %s",
       signature_index, CHECK);
     const Symbol* const sig = cp->symbol_at(signature_index);
     verify_legal_field_signature(name, sig, CHECK);
+    if (!access_flags.is_static()) instance_fields_count++;
 
     u2 constantvalue_index = 0;
     bool is_synthetic = false;
     u2 generic_signature_index = 0;
     const bool is_static = access_flags.is_static();
     FieldAnnotationCollector parsed_annotations(_loader_data);
 
+    bool is_null_restricted = false;
+
     const u2 attributes_count = cfs->get_u2_fast();
     if (attributes_count > 0) {
       parse_field_attributes(cfs,
                              attributes_count,
                              is_static,
@@ -1536,10 +1560,20 @@
           _fields_annotations = MetadataFactory::new_array<AnnotationArray*>(
                                              _loader_data, length, nullptr,
                                              CHECK);
         }
         _fields_annotations->at_put(n, parsed_annotations.field_annotations());
+        if (parsed_annotations.has_annotation(AnnotationCollector::_jdk_internal_NullRestricted)) {
+          if (!Signature::has_envelope(sig)) {
+            Exceptions::fthrow(
+              THREAD_AND_LOCATION,
+              vmSymbols::java_lang_ClassFormatError(),
+              "Illegal use of @jdk.internal.vm.annotation.NullRestricted annotation on field %s with signature %s (primitive types can never be null)",
+              name->as_C_string(), sig->as_C_string());
+          }
+          is_null_restricted = true;
+        }
         parsed_annotations.set_field_annotations(nullptr);
       }
       if (parsed_annotations.field_type_annotations() != nullptr) {
         if (_fields_type_annotations == nullptr) {
           _fields_type_annotations =
@@ -1561,11 +1595,14 @@
     }
 
     const BasicType type = cp->basic_type_for_signature_at(signature_index);
 
     // Update FieldAllocationCount for this kind of field
-    fac->update(is_static, type);
+    // This use of T_PRIMITIVE_OBJECT is not valid anymore => FIXME (relate to cleanup (removal?) of FiedAllocationCount
+    fac->update(is_static, type, type == T_PRIMITIVE_OBJECT);
+
+    if (is_null_restricted) fieldFlags.update_null_free_inline_type(true);
 
     FieldInfo fi(access_flags, name_index, signature_index, constantvalue_index, fieldFlags);
     fi.set_index(n);
     if (fieldFlags.is_generic()) {
       fi.set_generic_signature_index(generic_signature_index);
@@ -1609,15 +1646,57 @@
       fi.set_index(index);
       _temp_field_info->append(fi);
 
       // Update FieldAllocationCount for this kind of field
       const BasicType type = Signature::basic_type(injected[n].signature());
-      fac->update(false, type);
+      fac->update(false, type, false);
       index++;
     }
   }
 
+  if (is_inline_type) {
+    // Inject static ".default" field
+    FieldInfo::FieldFlags fflags(0);
+    fflags.update_injected(true);
+    AccessFlags aflags(JVM_ACC_STATIC);
+    FieldInfo fi(aflags,
+                 (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(default_value_name)),
+                 (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(object_signature)),
+                 0,
+                 fflags);
+      fi.set_index(index);
+      _temp_field_info->append(fi);
+
+    const BasicType type = Signature::basic_type(vmSymbols::object_signature());
+    fac->update(true, type, false);
+    index++;
+  }
+
+  if (is_inline_type && instance_fields_count == 0) {
+    // Inject ".empty" dummy field
+    _is_empty_inline_type = true;
+
+    FieldInfo::FieldFlags fflags(0);
+    fflags.update_injected(true);
+    AccessFlags aflags;
+    FieldInfo fi(aflags,
+                 (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(empty_marker_name)),
+                 (u2)vmSymbols::as_int(VM_SYMBOL_ENUM_NAME(byte_signature)),
+                 0,
+                 fflags);
+    fi.set_index(index);
+    _temp_field_info->append(fi);
+
+    const BasicType type = Signature::basic_type(vmSymbols::byte_signature());
+    fac->update(false, type, false);
+    index++;
+  }
+
+  if (instance_fields_count > 0) {
+    _has_nonstatic_fields = true;
+  }
+
   assert(_temp_field_info->length() == index, "Must be");
 
   if (_need_verify && length > 1) {
     // Check duplicated fields
     ResourceMark rm(THREAD);
@@ -1988,10 +2067,22 @@
     case VM_SYMBOL_ENUM_NAME(jdk_internal_ValueBased_signature): {
       if (_location != _in_class)   break;  // only allow for classes
       if (!privileged)              break;  // only allow in privileged code
       return _jdk_internal_ValueBased;
     }
+    case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ImplicitlyConstructible_signature): {
+      if (_location != _in_class)   break; // only allow for classes
+      return _jdk_internal_ImplicitlyConstructible;
+    }
+    case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_LooselyConsistentValue_signature): {
+      if (_location != _in_class)   break; // only allow for classes
+      return _jdk_internal_LooselyConsistentValue;
+    }
+    case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_NullRestricted_signature): {
+      if (_location != _in_field)   break; // only allow for fields
+      return _jdk_internal_NullRestricted;
+    }
     case VM_SYMBOL_ENUM_NAME(java_lang_Deprecated): {
       return _java_lang_Deprecated;
     }
     default: {
       break;
@@ -2226,10 +2317,12 @@
 //
 // The has_localvariable_table parameter is used to pass up the value to InstanceKlass.
 
 Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
                                       bool is_interface,
+                                      bool is_value_class,
+                                      bool is_abstract_class,
                                       const ConstantPool* cp,
                                       bool* const has_localvariable_table,
                                       TRAPS) {
   assert(cfs != nullptr, "invariant");
   assert(cp != nullptr, "invariant");
@@ -2267,18 +2360,27 @@
     } else {
       classfile_parse_error("Method <clinit> is not static in class file %s", THREAD);
       return nullptr;
     }
   } else {
-    verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL);
+    verify_legal_method_modifiers(flags, access_flags() , name, CHECK_NULL);
   }
 
   if (name == vmSymbols::object_initializer_name() && is_interface) {
     classfile_parse_error("Interface cannot have a method named <init>, class file %s", THREAD);
     return nullptr;
   }
 
+  if (EnableValhalla) {
+    if (((flags & JVM_ACC_SYNCHRONIZED) == JVM_ACC_SYNCHRONIZED)
+        && ((flags & JVM_ACC_STATIC) == 0 )
+        && !_access_flags.is_identity_class()) {
+      classfile_parse_error("Invalid synchronized method in non-identity class %s", THREAD);
+        return nullptr;
+    }
+  }
+
   int args_size = -1;  // only used when _need_verify is true
   if (_need_verify) {
     verify_legal_name_with_signature(name, signature, CHECK_NULL);
     args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) +
                  verify_legal_method_signature(name, signature, CHECK_NULL);
@@ -2839,10 +2941,12 @@
 
 
 // Side-effects: populates the _methods field in the parser
 void ClassFileParser::parse_methods(const ClassFileStream* const cfs,
                                     bool is_interface,
+                                    bool is_value_class,
+                                    bool is_abstract_type,
                                     bool* const has_localvariable_table,
                                     bool* has_final_method,
                                     bool* declares_nonstatic_concrete_methods,
                                     TRAPS) {
   assert(cfs != nullptr, "invariant");
@@ -2863,10 +2967,12 @@
                                                    CHECK);
 
     for (int index = 0; index < length; index++) {
       Method* method = parse_method(cfs,
                                     is_interface,
+                                    is_value_class,
+                                    is_abstract_type,
                                     _cp,
                                     has_localvariable_table,
                                     CHECK);
 
       if (method->is_final()) {
@@ -3128,23 +3234,35 @@
       inner_name_index, CHECK_0);
     if (_need_verify) {
       guarantee_property(inner_class_info_index != outer_class_info_index,
                          "Class is both outer and inner class in class file %s", CHECK_0);
     }
-    // Access flags
-    jint flags;
+
+    jint recognized_modifiers = RECOGNIZED_INNER_CLASS_MODIFIERS;
     // JVM_ACC_MODULE is defined in JDK-9 and later.
     if (_major_version >= JAVA_9_VERSION) {
-      flags = cfs->get_u2_fast() & (RECOGNIZED_INNER_CLASS_MODIFIERS | JVM_ACC_MODULE);
-    } else {
-      flags = cfs->get_u2_fast() & RECOGNIZED_INNER_CLASS_MODIFIERS;
+      recognized_modifiers |= JVM_ACC_MODULE;
     }
+
+    // Access flags
+    jint flags = cfs->get_u2_fast() & recognized_modifiers;
+
     if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
       // Set abstract bit for old class files for backward compatibility
       flags |= JVM_ACC_ABSTRACT;
     }
-    verify_legal_class_modifiers(flags, CHECK_0);
+
+    if (!supports_inline_types()) {
+      const bool is_module = (flags & JVM_ACC_MODULE) != 0;
+      const bool is_interface = (flags & JVM_ACC_INTERFACE) != 0;
+      if (!is_module && !is_interface) {
+        flags |= JVM_ACC_IDENTITY;
+      }
+    }
+
+    const char* name = inner_name_index == 0 ? "unnamed" : cp->symbol_at(inner_name_index)->as_utf8();
+    verify_legal_class_modifiers(flags, name, false, CHECK_0);
     AccessFlags inner_access_flags(flags);
 
     inner_classes->at_put(index++, inner_class_info_index);
     inner_classes->at_put(index++, outer_class_info_index);
     inner_classes->at_put(index++, inner_name_index);
@@ -3244,10 +3362,53 @@
   cfs->set_current(current_mark);
 
   return length;
 }
 
+u2 ClassFileParser::parse_classfile_loadable_descriptors_attribute(const ClassFileStream* const cfs,
+                                                                   const u1* const loadable_descriptors_attribute_start,
+                                                                   TRAPS) {
+  const u1* const current_mark = cfs->current();
+  u2 length = 0;
+  if (loadable_descriptors_attribute_start != nullptr) {
+    cfs->set_current(loadable_descriptors_attribute_start);
+    cfs->guarantee_more(2, CHECK_0);  // length
+    length = cfs->get_u2_fast();
+  }
+  const int size = length;
+  Array<u2>* const loadable_descriptors = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
+  _loadable_descriptors = loadable_descriptors;
+  if (length > 0) {
+    int index = 0;
+    cfs->guarantee_more(2 * length, CHECK_0);
+    for (int n = 0; n < length; n++) {
+      const u2 descriptor_index = cfs->get_u2_fast();
+      check_property(
+        valid_symbol_at(descriptor_index),
+        "LoadableDescriptors descriptor_index %u has bad constant type in class file %s",
+        descriptor_index, CHECK_0);
+      Symbol* descriptor = _cp->symbol_at(descriptor_index);
+      bool valid = legal_field_signature(descriptor, CHECK_0);
+      if(!valid) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(THREAD_AND_LOCATION,
+          vmSymbols::java_lang_ClassFormatError(),
+          "Descriptor from LoadableDescriptors attribute at index \"%d\" in class %s has illegal signature \"%s\"",
+          descriptor_index, _class_name->as_C_string(), descriptor->as_C_string());
+        return 0;
+      }
+      loadable_descriptors->at_put(index++, descriptor_index);
+    }
+    assert(index == size, "wrong size");
+  }
+
+  // Restore buffer's current position.
+  cfs->set_current(current_mark);
+
+  return length;
+}
+
 //  Record {
 //    u2 attribute_name_index;
 //    u4 attribute_length;
 //    u2 components_count;
 //    component_info components[components_count];
@@ -3528,16 +3689,19 @@
   _inner_classes = Universe::the_empty_short_array();
   // Set nest members attribute to default sentinel
   _nest_members = Universe::the_empty_short_array();
   // Set _permitted_subclasses attribute to default sentinel
   _permitted_subclasses = Universe::the_empty_short_array();
+  // Set _loadable_descriptors attribute to default sentinel
+  _loadable_descriptors = Universe::the_empty_short_array();
   cfs->guarantee_more(2, CHECK);  // attributes_count
   u2 attributes_count = cfs->get_u2_fast();
   bool parsed_sourcefile_attribute = false;
   bool parsed_innerclasses_attribute = false;
   bool parsed_nest_members_attribute = false;
   bool parsed_permitted_subclasses_attribute = false;
+  bool parsed_loadable_descriptors_attribute = false;
   bool parsed_nest_host_attribute = false;
   bool parsed_record_attribute = false;
   bool parsed_enclosingmethod_attribute = false;
   bool parsed_bootstrap_methods_attribute = false;
   const u1* runtime_visible_annotations = nullptr;
@@ -3559,10 +3723,12 @@
   u4  nest_members_attribute_length = 0;
   const u1* record_attribute_start = nullptr;
   u4  record_attribute_length = 0;
   const u1* permitted_subclasses_attribute_start = nullptr;
   u4  permitted_subclasses_attribute_length = 0;
+  const u1* loadable_descriptors_attribute_start = nullptr;
+  u4  loadable_descriptors_attribute_length = 0;
 
   // Iterate over attributes
   while (attributes_count--) {
     cfs->guarantee_more(6, CHECK);  // attribute_name_index, attribute_length
     const u2 attribute_name_index = cfs->get_u2_fast();
@@ -3785,10 +3951,19 @@
               }
               parsed_permitted_subclasses_attribute = true;
               permitted_subclasses_attribute_start = cfs->current();
               permitted_subclasses_attribute_length = attribute_length;
             }
+            if (EnableValhalla && tag == vmSymbols::tag_loadable_descriptors()) {
+              if (parsed_loadable_descriptors_attribute) {
+                classfile_parse_error("Multiple LoadableDescriptors attributes in class file %s", CHECK);
+                return;
+              }
+              parsed_loadable_descriptors_attribute = true;
+              loadable_descriptors_attribute_start = cfs->current();
+              loadable_descriptors_attribute_length = attribute_length;
+            }
           }
           // Skip attribute_length for any attribute where major_verson >= JAVA_17_VERSION
           cfs->skip_u1(attribute_length, CHECK);
         } else {
           // Unknown attribute
@@ -3865,10 +4040,22 @@
         permitted_subclasses_attribute_length == sizeof(num_subclasses) + sizeof(u2) * num_subclasses,
         "Wrong PermittedSubclasses attribute length in class file %s", CHECK);
     }
   }
 
+  if (parsed_loadable_descriptors_attribute) {
+    const u2 num_classes = parse_classfile_loadable_descriptors_attribute(
+                            cfs,
+                            loadable_descriptors_attribute_start,
+                            CHECK);
+    if (_need_verify) {
+      guarantee_property(
+        loadable_descriptors_attribute_length == sizeof(num_classes) + sizeof(u2) * num_classes,
+        "Wrong LoadableDescriptors attribute length in class file %s", CHECK);
+    }
+  }
+
   if (_max_bootstrap_specifier_index >= 0) {
     guarantee_property(parsed_bootstrap_methods_attribute,
                        "Missing BootstrapMethods attribute in class file %s", CHECK);
   }
 }
@@ -3930,13 +4117,16 @@
   this_klass->set_fields_status(_fields_status);
   this_klass->set_methods(_methods);
   this_klass->set_inner_classes(_inner_classes);
   this_klass->set_nest_members(_nest_members);
   this_klass->set_nest_host_index(_nest_host);
+  this_klass->set_loadable_descriptors(_loadable_descriptors);
   this_klass->set_annotations(_combined_annotations);
   this_klass->set_permitted_subclasses(_permitted_subclasses);
   this_klass->set_record_components(_record_components);
+  this_klass->set_inline_type_field_klasses_array(_inline_type_field_klasses);
+  this_klass->set_null_marker_offsets_array(_null_marker_offsets);
   // Delay the setting of _local_interfaces and _transitive_interfaces until after
   // initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could
   // be shared with _transitive_interfaces and _transitive_interfaces may be shared with
   // its _super. If an OOM occurs while loading the current klass, its _super field
   // may not have been set. When GC tries to free the klass, the _transitive_interfaces
@@ -3981,29 +4171,24 @@
   assert(cp != nullptr, "invariant");
   const InstanceKlass* super_klass = nullptr;
 
   if (super_class_index == 0) {
     check_property(_class_name == vmSymbols::java_lang_Object(),
-                   "Invalid superclass index %u in class file %s",
-                   super_class_index,
+                   "Invalid superclass index 0 in class file %s",
                    CHECK_NULL);
   } else {
     check_property(valid_klass_reference_at(super_class_index),
                    "Invalid superclass index %u in class file %s",
                    super_class_index,
                    CHECK_NULL);
     // The class name should be legal because it is checked when parsing constant pool.
     // However, make sure it is not an array type.
-    bool is_array = false;
     if (cp->tag_at(super_class_index).is_klass()) {
       super_klass = InstanceKlass::cast(cp->resolved_klass_at(super_class_index));
-      if (need_verify)
-        is_array = super_klass->is_array_klass();
-    } else if (need_verify) {
-      is_array = (cp->klass_name_at(super_class_index)->char_at(0) == JVM_SIGNATURE_ARRAY);
     }
     if (need_verify) {
+      bool is_array = (cp->klass_name_at(super_class_index)->char_at(0) == JVM_SIGNATURE_ARRAY);
       guarantee_property(!is_array,
                         "Bad superclass name in class file %s", CHECK_NULL);
     }
   }
   return super_klass;
@@ -4197,10 +4382,16 @@
     const jint lh = Klass::instance_layout_helper(ik->size_helper(), true);
     ik->set_layout_helper(lh);
   }
 }
 
+bool ClassFileParser::supports_inline_types() const {
+  // Inline types are only supported by class file version 67.65535 and later
+  return _major_version > JAVA_23_VERSION ||
+         (_major_version == JAVA_23_VERSION && _minor_version == JAVA_PREVIEW_MINOR_VERSION);
+}
+
 // utility methods for appending an array with check for duplicates
 
 static void append_interfaces(GrowableArray<InstanceKlass*>* result,
                               const Array<InstanceKlass*>* const ifs) {
   // iterate over new interfaces
@@ -4240,13 +4431,14 @@
     // no interfaces, use canonicalized array
     return Universe::the_empty_instance_klass_array();
   } else if (max_transitive_size == super_size) {
     // no new local interfaces added, share superklass' transitive interface array
     return super->transitive_interfaces();
-  } else if (max_transitive_size == local_size) {
-    // only local interfaces added, share local interface array
-    return local_ifs;
+    // The three lines below are commented to work around bug JDK-8245487
+//  } else if (max_transitive_size == local_size) {
+//    // only local interfaces added, share local interface array
+//    return local_ifs;
   } else {
     ResourceMark rm;
     GrowableArray<InstanceKlass*>* const result = new GrowableArray<InstanceKlass*>(max_transitive_size);
 
     // Copy down from superclass
@@ -4263,10 +4455,11 @@
     append_interfaces(result, local_ifs);
 
     // length will be less than the max_transitive_size if duplicates were removed
     const int length = result->length();
     assert(length <= max_transitive_size, "just checking");
+
     Array<InstanceKlass*>* const new_result =
       MetadataFactory::new_array<InstanceKlass*>(loader_data, length, CHECK_NULL);
     for (int i = 0; i < length; i++) {
       InstanceKlass* const e = result->at(i);
       assert(e != nullptr, "just checking");
@@ -4291,10 +4484,20 @@
     if (super_ik->is_sealed() && !super_ik->has_as_permitted_subclass(this_klass)) {
       classfile_icce_error("class %s cannot inherit from sealed class %s", super_ik, THREAD);
       return;
     }
 
+    // The JVMS says that super classes for value types must not have the ACC_IDENTITY
+    // flag set. But, java.lang.Object must still be allowed to be a direct super class
+    // for a value classes.  So, it is treated as a special case for now.
+    if (!this_klass->access_flags().is_identity_class() &&
+        super_ik->name() != vmSymbols::java_lang_Object() &&
+        super_ik->is_identity_class()) {
+      classfile_icce_error("value class %s cannot inherit from class %s", super_ik, THREAD);
+      return;
+    }
+
     // If the loader is not the boot loader then throw an exception if its
     // superclass is in package jdk.internal.reflect and its loader is not a
     // special reflection class loader
     if (!this_klass->class_loader_data()->is_the_null_class_loader_data()) {
       PackageEntry* super_package = super->package();
@@ -4476,12 +4679,13 @@
   }
 }
 
 // utility methods for format checking
 
-void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const {
+void ClassFileParser::verify_legal_class_modifiers(jint flags, const char* name, bool is_Object, TRAPS) const {
   const bool is_module = (flags & JVM_ACC_MODULE) != 0;
+  const bool is_inner_class = name != nullptr;
   assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set");
   if (is_module) {
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
@@ -4494,27 +4698,44 @@
   if (!_need_verify) { return; }
 
   const bool is_interface  = (flags & JVM_ACC_INTERFACE)  != 0;
   const bool is_abstract   = (flags & JVM_ACC_ABSTRACT)   != 0;
   const bool is_final      = (flags & JVM_ACC_FINAL)      != 0;
-  const bool is_super      = (flags & JVM_ACC_SUPER)      != 0;
+  const bool is_identity   = (flags & JVM_ACC_IDENTITY)   != 0;
   const bool is_enum       = (flags & JVM_ACC_ENUM)       != 0;
   const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0;
   const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION;
+  const bool valid_value_class = is_identity || is_interface ||
+                                 (supports_inline_types() && (!is_identity && (is_abstract || is_final)));
 
   if ((is_abstract && is_final) ||
       (is_interface && !is_abstract) ||
-      (is_interface && major_gte_1_5 && (is_super || is_enum)) ||
-      (!is_interface && major_gte_1_5 && is_annotation)) {
+      (is_interface && major_gte_1_5 && (is_identity || is_enum)) ||   //  ACC_SUPER (now ACC_IDENTITY) was illegal for interfaces
+      (!is_interface && major_gte_1_5 && is_annotation) ||
+      (!valid_value_class)) {
     ResourceMark rm(THREAD);
-    Exceptions::fthrow(
-      THREAD_AND_LOCATION,
-      vmSymbols::java_lang_ClassFormatError(),
-      "Illegal class modifiers in class %s: 0x%X",
-      _class_name->as_C_string(), flags
-    );
-    return;
+    const char* class_note = "";
+    if (!valid_value_class) {
+      class_note = " (a value class must be final or else abstract)";
+    }
+    if (name == nullptr) { // Not an inner class
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_ClassFormatError(),
+        "Illegal class modifiers in class %s%s: 0x%X",
+        _class_name->as_C_string(), class_note, flags
+      );
+      return;
+    } else {
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_ClassFormatError(),
+        "Illegal class modifiers in declaration of inner class %s%s of class %s: 0x%X",
+        name, class_note, _class_name->as_C_string(), flags
+      );
+      return;
+    }
   }
 }
 
 static bool has_illegal_visibility(jint flags) {
   const bool is_public    = (flags & JVM_ACC_PUBLIC)    != 0;
@@ -4576,12 +4797,12 @@
     classfile_ucve_error("%s (class file version %u.%u) was compiled with an invalid non-zero minor version",
                          class_name, major, minor, THREAD);
   }
 }
 
-void ClassFileParser::verify_legal_field_modifiers(jint flags,
-                                                   bool is_interface,
+void ClassFileParser:: verify_legal_field_modifiers(jint flags,
+                                                   AccessFlags class_access_flags,
                                                    TRAPS) const {
   if (!_need_verify) { return; }
 
   const bool is_public    = (flags & JVM_ACC_PUBLIC)    != 0;
   const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0;
@@ -4589,39 +4810,73 @@
   const bool is_static    = (flags & JVM_ACC_STATIC)    != 0;
   const bool is_final     = (flags & JVM_ACC_FINAL)     != 0;
   const bool is_volatile  = (flags & JVM_ACC_VOLATILE)  != 0;
   const bool is_transient = (flags & JVM_ACC_TRANSIENT) != 0;
   const bool is_enum      = (flags & JVM_ACC_ENUM)      != 0;
+  const bool is_strict    = (flags & JVM_ACC_STRICT)    != 0;
   const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION;
 
+  const bool is_interface = class_access_flags.is_interface();
+  const bool is_identity_class = class_access_flags.is_identity_class();
+
   bool is_illegal = false;
+  const char* error_msg = "";
 
-  if (is_interface) {
-    if (!is_public || !is_static || !is_final || is_private ||
-        is_protected || is_volatile || is_transient ||
-        (major_gte_1_5 && is_enum)) {
+  // There is some overlap in the checks that apply, for example interface fields
+  // must be static, static fields can't be strict, and therefore interfaces can't
+  // have strict fields. So we don't have to check every possible invalid combination
+  // individually as long as all are covered. Once we have found an illegal combination
+  // we can stop checking.
+
+  if (supports_inline_types()) {
+    if (is_strict && is_static) {
       is_illegal = true;
+      error_msg = "field cannot be strict and static";
     }
-  } else { // not interface
-    if (has_illegal_visibility(flags) || (is_final && is_volatile)) {
+    else if (is_strict && !is_final) {
       is_illegal = true;
+      error_msg = "strict field must be final";
+    }
+  }
+
+  if (!is_illegal) {
+    if (is_interface) {
+      if (!is_public || !is_static || !is_final || is_private ||
+          is_protected || is_volatile || is_transient ||
+          (major_gte_1_5 && is_enum)) {
+        is_illegal = true;
+        error_msg = "interface fields must be public, static and final, and may be synthetic";
+      }
+    } else { // not interface
+      if (has_illegal_visibility(flags)) {
+        is_illegal = true;
+        error_msg = "invalid visibility flags for class field";
+      } else if (is_final && is_volatile) {
+        is_illegal = true;
+        error_msg = "fields cannot be final and volatile";
+      } else if (supports_inline_types()) {
+        if (!is_identity_class && !is_static && !is_strict) {
+          is_illegal = true;
+          error_msg = "value class fields must be either strict or static";
+        }
+      }
     }
   }
 
   if (is_illegal) {
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
       vmSymbols::java_lang_ClassFormatError(),
-      "Illegal field modifiers in class %s: 0x%X",
-      _class_name->as_C_string(), flags);
+      "Illegal field modifiers (%s) in class %s: 0x%X",
+      error_msg, _class_name->as_C_string(), flags);
     return;
   }
 }
 
 void ClassFileParser::verify_legal_method_modifiers(jint flags,
-                                                    bool is_interface,
+                                                    AccessFlags class_access_flags,
                                                     const Symbol* name,
                                                     TRAPS) const {
   if (!_need_verify) { return; }
 
   const bool is_public       = (flags & JVM_ACC_PUBLIC)       != 0;
@@ -4636,13 +4891,18 @@
   const bool is_protected    = (flags & JVM_ACC_PROTECTED)    != 0;
   const bool major_gte_1_5   = _major_version >= JAVA_1_5_VERSION;
   const bool major_gte_8     = _major_version >= JAVA_8_VERSION;
   const bool major_gte_17    = _major_version >= JAVA_17_VERSION;
   const bool is_initializer  = (name == vmSymbols::object_initializer_name());
+  // LW401 CR required: removal of value factories support
+  const bool is_interface    = class_access_flags.is_interface();
+  const bool is_identity_class = class_access_flags.is_identity_class();
+  const bool is_abstract_class = class_access_flags.is_abstract();
 
   bool is_illegal = false;
 
+  const char* class_note = "";
   if (is_interface) {
     if (major_gte_8) {
       // Class file version is JAVA_8_VERSION or later Methods of
       // interfaces may set any of the flags except ACC_PROTECTED,
       // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must
@@ -4678,14 +4938,19 @@
         if (is_static || is_final || is_synchronized || is_native ||
             is_abstract || (major_gte_1_5 && is_bridge)) {
           is_illegal = true;
         }
       } else { // not initializer
-        if (is_abstract) {
-          if ((is_final || is_native || is_private || is_static ||
-              (major_gte_1_5 && (is_synchronized || (!major_gte_17 && is_strict))))) {
-            is_illegal = true;
+        if (!is_identity_class && is_synchronized && !is_static) {
+          is_illegal = true;
+          class_note = " (not an identity class)";
+        } else {
+          if (is_abstract) {
+            if ((is_final || is_native || is_private || is_static ||
+                (major_gte_1_5 && (is_synchronized || (!major_gte_17 && is_strict))))) {
+              is_illegal = true;
+            }
           }
         }
       }
     }
   }
@@ -4693,12 +4958,13 @@
   if (is_illegal) {
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
       vmSymbols::java_lang_ClassFormatError(),
-      "Method %s in class %s has illegal modifiers: 0x%X",
-      name->as_C_string(), _class_name->as_C_string(), flags);
+      "Method %s in class %s%s has illegal modifiers: 0x%X",
+      name->as_C_string(), _class_name->as_C_string(),
+      class_note, flags);
     return;
   }
 }
 
 void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,
@@ -4751,10 +5017,19 @@
     }
   }
   return true;
 }
 
+bool ClassFileParser::is_class_in_loadable_descriptors_attribute(Symbol *klass) {
+  if (_loadable_descriptors == nullptr) return false;
+  for (int i = 0; i < _loadable_descriptors->length(); i++) {
+        Symbol* class_name = _cp->symbol_at(_loadable_descriptors->at(i));
+        if (class_name == klass) return true;
+  }
+  return false;
+}
+
 // Take pointer to a UTF8 byte string (not NUL-terminated).
 // Skip over the longest part of the string that could
 // be taken as a fieldname. Allow non-trailing '/'s if slash_ok is true.
 // Return a pointer to just past the fieldname.
 // Return null if no fieldname at all was found, or in the case of slash_ok
@@ -4852,22 +5127,23 @@
     case JVM_SIGNATURE_INT:
     case JVM_SIGNATURE_FLOAT:
     case JVM_SIGNATURE_LONG:
     case JVM_SIGNATURE_DOUBLE:
       return signature + 1;
-    case JVM_SIGNATURE_CLASS: {
+    case JVM_SIGNATURE_CLASS:
+    {
       if (_major_version < JAVA_1_5_VERSION) {
         // Skip over the class name if one is there
         const char* const p = skip_over_field_name(signature + 1, true, --length);
 
         // The next character better be a semicolon
         if (p && (p - signature) > 1 && p[0] == JVM_SIGNATURE_ENDCLASS) {
           return p + 1;
         }
       }
       else {
-        // Skip leading 'L' and ignore first appearance of ';'
+        // Skip leading 'L' or 'Q' and ignore first appearance of ';'
         signature++;
         const char* c = (const char*) memchr(signature, JVM_SIGNATURE_ENDCLASS, length - 1);
         // Format check signature
         if (c != nullptr) {
           int newlen = pointer_delta_as_int(c, (char*) signature);
@@ -4919,10 +5195,14 @@
     } else if (_major_version < JAVA_1_5_VERSION) {
       if (bytes[0] != JVM_SIGNATURE_SPECIAL) {
         p = skip_over_field_name(bytes, true, length);
         legal = (p != nullptr) && ((p - bytes) == (int)length);
       }
+    } else if ((_major_version >= CONSTANT_CLASS_DESCRIPTORS || _class_name->starts_with("jdk/internal/reflect/"))
+                   && bytes[length - 1] == ';' ) {
+      // Support for L...; and Q...; descriptors
+      legal = verify_unqualified_name(bytes + 1, length - 2, LegalClass);
     } else {
       // 4900761: relax the constraints based on JSR202 spec
       // Class names may be drawn from the entire Unicode character set.
       // Identifiers between '/' must be unqualified names.
       // The utf8 string has been verified when parsing cpool entries.
@@ -4984,11 +5264,12 @@
   unsigned int length = name->utf8_length();
   bool legal = false;
 
   if (length > 0) {
     if (bytes[0] == JVM_SIGNATURE_SPECIAL) {
-      if (name == vmSymbols::object_initializer_name() || name == vmSymbols::class_initializer_name()) {
+      if (name == vmSymbols::object_initializer_name() ||
+          name == vmSymbols::class_initializer_name()) {
         legal = true;
       }
     } else if (_major_version < JAVA_1_5_VERSION) {
       const char* p;
       p = skip_over_field_name(bytes, false, length);
@@ -5010,10 +5291,20 @@
     );
     return;
   }
 }
 
+bool ClassFileParser::legal_field_signature(const Symbol* signature, TRAPS) const {
+  const char* const bytes = (const char*)signature->bytes();
+  const unsigned int length = signature->utf8_length();
+  const char* const p = skip_over_field_signature(bytes, false, length, CHECK_false);
+
+  if (p == nullptr || (p - bytes) != (int)length) {
+    return false;
+  }
+  return true;
+}
 
 // Checks if signature is a legal field signature.
 void ClassFileParser::verify_legal_field_signature(const Symbol* name,
                                                    const Symbol* signature,
                                                    TRAPS) const {
@@ -5045,13 +5336,13 @@
     return;
   }
 
   int sig_length = signature->utf8_length();
   if (name->utf8_length() > 0 &&
-      name->char_at(0) == JVM_SIGNATURE_SPECIAL &&
-      sig_length > 0 &&
-      signature->char_at(sig_length - 1) != JVM_SIGNATURE_VOID) {
+    name->char_at(0) == JVM_SIGNATURE_SPECIAL &&
+    sig_length > 0 &&
+    signature->char_at(sig_length - 1) != JVM_SIGNATURE_VOID) {
     throwIllegalSignature("Method", name, signature, THREAD);
   }
 }
 
 // Checks if signature is a legal method signature.
@@ -5224,11 +5515,10 @@
   }
 
   fill_instance_klass(ik, changed_by_loadhook, cl_inst_info, CHECK_NULL);
 
   assert(_klass == ik, "invariant");
-
   return ik;
 }
 
 void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
                                           bool changed_by_loadhook,
@@ -5260,16 +5550,23 @@
   ik->set_should_verify_class(_need_verify);
 
   // Not yet: supers are done below to support the new subtype-checking fields
   ik->set_nonstatic_field_size(_field_info->_nonstatic_field_size);
   ik->set_has_nonstatic_fields(_field_info->_has_nonstatic_fields);
+  if (_field_info->_is_naturally_atomic && ik->is_inline_klass()) {
+    ik->set_is_naturally_atomic();
+  }
+
   assert(_fac != nullptr, "invariant");
-  ik->set_static_oop_field_count(_fac->count[STATIC_OOP]);
+  ik->set_static_oop_field_count(_fac->count[STATIC_OOP] + _fac->count[STATIC_INLINE]);
 
   // this transfers ownership of a lot of arrays from
   // the parser onto the InstanceKlass*
   apply_parsed_class_metadata(ik, _java_fields_count);
+  if (ik->is_inline_klass()) {
+    InlineKlass::cast(ik)->init_fixed_block();
+  }
 
   // can only set dynamic nest-host after static nest information is set
   if (cl_inst_info.dynamic_nest_host() != nullptr) {
     ik->set_nest_host(cl_inst_info.dynamic_nest_host());
   }
@@ -5279,13 +5576,15 @@
   assert(nullptr == _fieldinfo_stream, "invariant");
   assert(nullptr == _fields_status, "invariant");
   assert(nullptr == _methods, "invariant");
   assert(nullptr == _inner_classes, "invariant");
   assert(nullptr == _nest_members, "invariant");
+  assert(nullptr == _loadable_descriptors, "invariant");
   assert(nullptr == _combined_annotations, "invariant");
   assert(nullptr == _record_components, "invariant");
   assert(nullptr == _permitted_subclasses, "invariant");
+  assert(nullptr == _inline_type_field_klasses, "invariant");
 
   if (_has_localvariable_table) {
     ik->set_has_localvariable_table(true);
   }
 
@@ -5317,10 +5616,16 @@
   ik->set_minor_version(_minor_version);
   ik->set_major_version(_major_version);
   ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods);
   ik->set_declares_nonstatic_concrete_methods(_declares_nonstatic_concrete_methods);
 
+  if (_must_be_atomic) {
+    ik->set_must_be_atomic();
+  }
+  if (_is_implicitly_constructible) {
+    ik->set_is_implicitly_constructible();
+  }
   if (_is_hidden) {
     ik->set_is_hidden();
   }
 
   // Set PackageEntry for this_klass
@@ -5423,10 +5728,38 @@
       // We won a potential race
       JvmtiExport::add_default_read_edges(module_handle, THREAD);
     }
   }
 
+  bool all_fields_empty = true;
+  for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
+    if (!fs.access_flags().is_static()) {
+      if (fs.field_descriptor().is_null_free_inline_type()) {
+        Klass* k = ik->inline_type_field_klasses_array()->at(fs.index());
+        assert(k->is_inline_klass(), "must be");
+        if (!InlineKlass::cast(k)->is_empty_inline_type()) { all_fields_empty = false; }
+      } else {
+        all_fields_empty = false;
+      }
+    } else if (is_inline_type() && (fs.name() == vmSymbols::default_value_name())) {
+      InlineKlass::cast(ik)->set_default_value_offset(ik->field_offset(fs.index()));
+    }
+  }
+
+  if (_is_empty_inline_type || (is_inline_type() && all_fields_empty)) {
+    ik->set_is_empty_inline_type();
+  }
+
+  if (is_inline_type()) {
+    InlineKlass* vk = InlineKlass::cast(ik);
+    vk->set_alignment(_alignment);
+    vk->set_first_field_offset(_first_field_offset);
+    vk->set_payload_size_in_bytes(_payload_size_in_bytes);
+    vk->set_internal_null_marker_offset(_internal_null_marker_offset);
+    InlineKlass::cast(ik)->initialize_calling_convention(CHECK);
+  }
+
   ClassLoadingService::notify_class_loaded(ik, false /* not shared class */);
 
   if (!is_internal()) {
     ik->print_class_load_logging(_loader_data, module_entry, _stream);
 
@@ -5514,12 +5847,14 @@
   _methods(nullptr),
   _inner_classes(nullptr),
   _nest_members(nullptr),
   _nest_host(0),
   _permitted_subclasses(nullptr),
+  _loadable_descriptors(nullptr),
   _record_components(nullptr),
   _local_interfaces(nullptr),
+  _local_interface_indexes(nullptr),
   _transitive_interfaces(nullptr),
   _combined_annotations(nullptr),
   _class_annotations(nullptr),
   _class_type_annotations(nullptr),
   _fields_annotations(nullptr),
@@ -5527,10 +5862,12 @@
   _klass(nullptr),
   _klass_to_deallocate(nullptr),
   _parsed_annotations(nullptr),
   _fac(nullptr),
   _field_info(nullptr),
+  _inline_type_field_klasses(nullptr),
+  _null_marker_offsets(nullptr),
   _temp_field_info(nullptr),
   _method_ordering(nullptr),
   _all_mirandas(nullptr),
   _vtable_size(0),
   _itable_size(0),
@@ -5555,10 +5892,18 @@
   _has_nonstatic_concrete_methods(false),
   _declares_nonstatic_concrete_methods(false),
   _has_localvariable_table(false),
   _has_final_method(false),
   _has_contended_fields(false),
+  _has_inline_type_fields(false),
+  _has_nonstatic_fields(false),
+  _is_empty_inline_type(false),
+  _is_naturally_atomic(false),
+  _must_be_atomic(true),
+  _is_implicitly_constructible(false),
+  _has_loosely_consistent_annotation(false),
+  _has_implicitly_constructible_annotation(false),
   _has_finalizer(false),
   _has_empty_finalizer(false),
   _has_vanilla_constructor(false),
   _max_bootstrap_specifier_index(-1) {
 
@@ -5605,14 +5950,17 @@
   _fields_status = nullptr;
   _methods = nullptr;
   _inner_classes = nullptr;
   _nest_members = nullptr;
   _permitted_subclasses = nullptr;
+  _loadable_descriptors = nullptr;
   _combined_annotations = nullptr;
   _class_annotations = _class_type_annotations = nullptr;
   _fields_annotations = _fields_type_annotations = nullptr;
   _record_components = nullptr;
+  _inline_type_field_klasses = nullptr;
+  _null_marker_offsets = nullptr;
 }
 
 // Destructor to clean up
 ClassFileParser::~ClassFileParser() {
   _class_name->decrement_refcount();
@@ -5627,10 +5975,18 @@
 
   if (_fields_status != nullptr) {
     MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status);
   }
 
+  if (_inline_type_field_klasses != nullptr) {
+     MetadataFactory::free_array<InlineKlass*>(_loader_data, _inline_type_field_klasses);
+  }
+
+  if (_null_marker_offsets != nullptr) {
+     MetadataFactory::free_array<int>(_loader_data, _null_marker_offsets);
+  }
+
   if (_methods != nullptr) {
     // Free methods
     InstanceKlass::deallocate_methods(_loader_data, _methods);
   }
 
@@ -5649,10 +6005,14 @@
 
   if (_permitted_subclasses != nullptr && _permitted_subclasses != Universe::the_empty_short_array()) {
     MetadataFactory::free_array<u2>(_loader_data, _permitted_subclasses);
   }
 
+  if (_loadable_descriptors != nullptr && _loadable_descriptors != Universe::the_empty_short_array()) {
+    MetadataFactory::free_array<u2>(_loader_data, _loadable_descriptors);
+  }
+
   // Free interfaces
   InstanceKlass::deallocate_interfaces(_loader_data, _super_klass,
                                        _local_interfaces, _transitive_interfaces);
 
   if (_combined_annotations != nullptr) {
@@ -5733,35 +6093,33 @@
   assert(cp_size == (u2)cp->length(), "invariant");
 
   // ACCESS FLAGS
   stream->guarantee_more(8, CHECK);  // flags, this_class, super_class, infs_len
 
-  // Access flags
-  jint flags;
+  jint recognized_modifiers = JVM_RECOGNIZED_CLASS_MODIFIERS;
   // JVM_ACC_MODULE is defined in JDK-9 and later.
   if (_major_version >= JAVA_9_VERSION) {
-    flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE);
-  } else {
-    flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;
+    recognized_modifiers |= JVM_ACC_MODULE;
   }
 
+  // Access flags
+  jint flags = stream->get_u2_fast() & recognized_modifiers;
+
   if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) {
     // Set abstract bit for old class files for backward compatibility
     flags |= JVM_ACC_ABSTRACT;
   }
 
-  verify_legal_class_modifiers(flags, CHECK);
-
-  short bad_constant = class_bad_constant_seen();
-  if (bad_constant != 0) {
-    // Do not throw CFE until after the access_flags are checked because if
-    // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
-    classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD);
-    return;
+  // Fixing ACC_SUPER/ACC_IDENTITY for old class files
+  if (!supports_inline_types()) {
+    const bool is_module = (flags & JVM_ACC_MODULE) != 0;
+    const bool is_interface = (flags & JVM_ACC_INTERFACE) != 0;
+    if (!is_module && !is_interface) {
+      flags |= JVM_ACC_IDENTITY;
+    }
   }
 
-  _access_flags.set_flags(flags);
 
   // This class and superclass
   _this_class_index = stream->get_u2_fast();
   check_property(
     valid_cp_range(_this_class_index, cp_size) &&
@@ -5770,10 +6128,24 @@
     _this_class_index, CHECK);
 
   Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index);
   assert(class_name_in_cp != nullptr, "class_name can't be null");
 
+  bool is_java_lang_Object = class_name_in_cp == vmSymbols::java_lang_Object();
+
+  verify_legal_class_modifiers(flags, nullptr, is_java_lang_Object, CHECK);
+
+  _access_flags.set_flags(flags);
+
+  short bad_constant = class_bad_constant_seen();
+  if (bad_constant != 0) {
+    // Do not throw CFE until after the access_flags are checked because if
+    // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
+    classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD);
+    return;
+  }
+
   // Don't need to check whether this class name is legal or not.
   // It has been checked when constant pool is parsed.
   // However, make sure it is not an array type.
   if (_need_verify) {
     guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY,
@@ -5849,27 +6221,27 @@
                    _itfs_len,
                    cp,
                    &_has_nonstatic_concrete_methods,
                    CHECK);
 
-  assert(_local_interfaces != nullptr, "invariant");
-
   // Fields (offsets are filled in later)
   _fac = new FieldAllocationCount();
   parse_fields(stream,
-               _access_flags.is_interface(),
+               _access_flags,
                _fac,
                cp,
                cp_size,
                &_java_fields_count,
                CHECK);
 
   assert(_temp_field_info != nullptr, "invariant");
 
   // Methods
   parse_methods(stream,
-                _access_flags.is_interface(),
+                is_interface(),
+                !is_identity_class(),
+                is_abstract_class(),
                 &_has_localvariable_table,
                 &_has_final_method,
                 &_declares_nonstatic_concrete_methods,
                 CHECK);
 
@@ -5945,17 +6317,17 @@
   assert(cp != nullptr, "invariant");
   assert(_loader_data != nullptr, "invariant");
 
   if (_class_name == vmSymbols::java_lang_Object()) {
     check_property(_local_interfaces == Universe::the_empty_instance_klass_array(),
-                   "java.lang.Object cannot implement an interface in class file %s",
-                   CHECK);
+        "java.lang.Object cannot implement an interface in class file %s",
+        CHECK);
   }
   // We check super class after class file is parsed and format is checked
   if (_super_class_index > 0 && nullptr == _super_klass) {
     Symbol* const super_class_name = cp->klass_name_at(_super_class_index);
-    if (_access_flags.is_interface()) {
+    if (is_interface()) {
       // Before attempting to resolve the superclass, check for class format
       // errors not checked yet.
       guarantee_property(super_class_name == vmSymbols::java_lang_Object(),
         "Interfaces must have java.lang.Object as superclass in class file %s",
         CHECK);
@@ -5963,30 +6335,118 @@
     Handle loader(THREAD, _loader_data->class_loader());
     if (loader.is_null() && super_class_name == vmSymbols::java_lang_Object()) {
       _super_klass = vmClasses::Object_klass();
     } else {
       _super_klass = (const InstanceKlass*)
-                       SystemDictionary::resolve_super_or_fail(_class_name,
+                       SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name,
                                                                super_class_name,
                                                                loader,
                                                                _protection_domain,
                                                                true,
                                                                CHECK);
     }
   }
 
   if (_super_klass != nullptr) {
+    if (_super_klass->is_interface()) {
+      classfile_icce_error("class %s has interface %s as super class", _super_klass, THREAD);
+      return;
+    }
+
+    if (_super_klass->is_final()) {
+      classfile_icce_error("class %s cannot inherit from final class %s", _super_klass, THREAD);
+      return;
+    }
+
+    if (EnableValhalla) {
+      check_identity_and_value_modifiers(this, _super_klass, CHECK);
+    }
+
     if (_super_klass->has_nonstatic_concrete_methods()) {
       _has_nonstatic_concrete_methods = true;
     }
+  }
 
-    if (_super_klass->is_interface()) {
-      classfile_icce_error("class %s has interface %s as super class", _super_klass, THREAD);
-      return;
+  if (_parsed_annotations->has_annotation(AnnotationCollector::_jdk_internal_LooselyConsistentValue) && _access_flags.is_identity_class()) {
+    THROW_MSG(vmSymbols::java_lang_ClassFormatError(),
+          err_msg("class %s cannot have annotation jdk.internal.vm.annotation.LooselyConsistentValue, because it is not a value class",
+                  _class_name->as_klass_external_name()));
+  }
+  if (_parsed_annotations->has_annotation(AnnotationCollector::_jdk_internal_ImplicitlyConstructible) && _access_flags.is_identity_class()) {
+    THROW_MSG(vmSymbols::java_lang_ClassFormatError(),
+          err_msg("class %s cannot have annotation jdk.internal.vm.annotation.ImplicitlyConstructible, because it is not a value class",
+                  _class_name->as_klass_external_name()));
+  }
+
+  // Determining is the class allows tearing or not (default is not)
+  // Test might need extensions when field inheritance is added for value classes
+  if (EnableValhalla && !_access_flags.is_identity_class()) {
+    if (_parsed_annotations->has_annotation(ClassAnnotationCollector::_jdk_internal_LooselyConsistentValue)
+        && (_super_klass == vmClasses::Object_klass() || !_super_klass->must_be_atomic())) {
+      _must_be_atomic = false;
+    }
+    if (_parsed_annotations->has_annotation(ClassAnnotationCollector::_jdk_internal_ImplicitlyConstructible)
+        && (_super_klass == vmClasses::Object_klass() || _super_klass->is_implicitly_constructible())) {
+      _is_implicitly_constructible = true;
+    }
+    // Apply VM options override
+    if (*ForceNonTearable != '\0') {
+      // Allow a command line switch to force the same atomicity property:
+      const char* class_name_str = _class_name->as_C_string();
+      if (StringUtils::class_list_match(ForceNonTearable, class_name_str)) {
+        _must_be_atomic = true;
+      }
     }
   }
 
+  int itfs_len = _local_interface_indexes == nullptr ? 0 : _local_interface_indexes->length();
+  _local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, nullptr, CHECK);
+  if (_local_interface_indexes != nullptr) {
+    for (int i = 0; i < _local_interface_indexes->length(); i++) {
+      u2 interface_index = _local_interface_indexes->at(i);
+      Klass* interf;
+      if (cp->tag_at(interface_index).is_klass()) {
+        interf = cp->resolved_klass_at(interface_index);
+      } else {
+        Symbol* const unresolved_klass  = cp->klass_name_at(interface_index);
+
+        // Don't need to check legal name because it's checked when parsing constant pool.
+        // But need to make sure it's not an array type.
+        guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY,
+                            "Bad interface name in class file %s", CHECK);
+
+        // Call resolve_super so class circularity is checked
+        interf = SystemDictionary::resolve_with_circularity_detection_or_fail(
+                                                  _class_name,
+                                                  unresolved_klass,
+                                                  Handle(THREAD, _loader_data->class_loader()),
+                                                  _protection_domain,
+                                                  false,
+                                                  CHECK);
+      }
+
+      if (!interf->is_interface()) {
+        THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                  err_msg("class %s can not implement %s, because it is not an interface (%s)",
+                          _class_name->as_klass_external_name(),
+                          interf->external_name(),
+                          interf->class_in_module_of_loader()));
+      }
+
+      if (EnableValhalla) {
+        // Check modifiers and set carries_identity_modifier/carries_value_modifier flags
+        check_identity_and_value_modifiers(this, InstanceKlass::cast(interf), CHECK);
+      }
+
+      if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
+        _has_nonstatic_concrete_methods = true;
+      }
+      _local_interfaces->at_put(i, InstanceKlass::cast(interf));
+    }
+  }
+  assert(_local_interfaces != nullptr, "invariant");
+
   // Compute the transitive list of all unique interfaces implemented by this class
   _transitive_interfaces =
     compute_transitive_interfaces(_super_klass,
                                   _local_interfaces,
                                   _loader_data,
@@ -6010,28 +6470,125 @@
                                                     loader,
                                                     _class_name,
                                                     _local_interfaces);
 
   // Size of Java itable (in words)
-  _itable_size = _access_flags.is_interface() ? 0 :
+  _itable_size = is_interface() ? 0 :
     klassItable::compute_itable_size(_transitive_interfaces);
 
   assert(_fac != nullptr, "invariant");
   assert(_parsed_annotations != nullptr, "invariant");
 
+  if (EnableValhalla) {
+    _inline_type_field_klasses = MetadataFactory::new_array<InlineKlass*>(_loader_data,
+                                                   java_fields_count(),
+                                                   nullptr,
+                                                   CHECK);
+    for (GrowableArrayIterator<FieldInfo> it = _temp_field_info->begin(); it != _temp_field_info->end(); ++it) {
+      FieldInfo fieldinfo = *it;
+      if (fieldinfo.access_flags().is_static()) continue;  // Only non-static fields are processed at load time
+      Symbol* sig = fieldinfo.signature(cp);
+      if (fieldinfo.field_flags().is_null_free_inline_type()) {
+        // Pre-load classes of null-free fields that are candidate for flattening
+        TempNewSymbol s = Signature::strip_envelope(sig);
+        if (s == _class_name) {
+          THROW_MSG(vmSymbols::java_lang_ClassCircularityError(), err_msg("Class %s cannot have a null-free non-static field of its own type", _class_name->as_C_string()));
+        }
+        log_info(class, preload)("Preloading class %s during loading of class %s. Cause: a null-free non-static field is declared with this type", s->as_C_string(), _class_name->as_C_string());
+        Klass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, s, Handle(THREAD, _loader_data->class_loader()), _protection_domain, false, THREAD);
+        if (HAS_PENDING_EXCEPTION) {
+          log_warning(class, preload)("Preloading of class %s during loading of class %s (cause: null-free non-static field) failed: %s",
+                                      s->as_C_string(), _class_name->as_C_string(), PENDING_EXCEPTION->klass()->name()->as_C_string());
+          return; // Exception is still pending
+        }
+        assert(klass != nullptr, "Sanity check");
+        if (klass->access_flags().is_identity_class()) {
+          assert(klass->is_instance_klass(), "Sanity check");
+          ResourceMark rm(THREAD);
+          THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                    err_msg("Class %s expects class %s to be a value class, but it is an identity class",
+                    _class_name->as_C_string(),
+                    InstanceKlass::cast(klass)->external_name()));
+        }
+        if (klass->is_abstract()) {
+          assert(klass->is_instance_klass(), "Sanity check");
+          ResourceMark rm(THREAD);
+          THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                    err_msg("Class %s expects class %s to be concrete value type, but it is an abstract class",
+                    _class_name->as_C_string(),
+                    InstanceKlass::cast(klass)->external_name()));
+        }
+        InlineKlass* vk = InlineKlass::cast(klass);
+        if (!vk->is_implicitly_constructible()) {
+          THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
+                    err_msg("class %s is not implicitly constructible and it is used in a null restricted non-static field (not supported)",
+                    klass->name()->as_C_string()));
+        }
+        _inline_type_field_klasses->at_put(fieldinfo.index(), vk);
+        log_info(class, preload)("Preloading of class %s during loading of class %s (cause: null-free non-static field) succeeded", s->as_C_string(), _class_name->as_C_string());
+      } else if (Signature::has_envelope(sig)) {
+        // Preloading classes for nullable fields that are listed in the LoadableDescriptors attribute
+        // Those classes would be required later for the flattening of nullable inline type fields
+        TempNewSymbol name = Signature::strip_envelope(sig);
+        if (name != _class_name && is_class_in_loadable_descriptors_attribute(sig)) {
+          log_info(class, preload)("Preloading class %s during loading of class %s. Cause: field type in LoadableDescriptors attribute", name->as_C_string(), _class_name->as_C_string());
+          oop loader = loader_data()->class_loader();
+          Klass* klass = SystemDictionary::resolve_with_circularity_detection_or_fail(_class_name, name, Handle(THREAD, loader), _protection_domain, false, THREAD);
+          if (klass != nullptr) {
+            if (klass->is_inline_klass()) {
+              _inline_type_field_klasses->at_put(fieldinfo.index(), InlineKlass::cast(klass));
+              log_info(class, preload)("Preloading of class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) succeeded", name->as_C_string(), _class_name->as_C_string());
+            } else {
+              // Non value class are allowed by the current spec, but it could be an indication of an issue so let's log a warning
+              log_warning(class, preload)("Preloading class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) but loaded class is not a value class", name->as_C_string(), _class_name->as_C_string());
+            }
+            } else {
+            log_warning(class, preload)("Preloading of class %s during loading of class %s (cause: field type in LoadableDescriptors attribute) failed : %s",
+                                          name->as_C_string(), _class_name->as_C_string(), PENDING_EXCEPTION->klass()->name()->as_C_string());
+          }
+          // Loads triggered by the LoadableDescriptors attribute are speculative, failures must not impact loading of current class
+          if (HAS_PENDING_EXCEPTION) {
+            CLEAR_PENDING_EXCEPTION;
+          }
+        }
+      }
+    }
+  }
+
   _field_info = new FieldLayoutInfo();
-  FieldLayoutBuilder lb(class_name(), super_klass(), _cp, /*_fields*/ _temp_field_info,
-                        _parsed_annotations->is_contended(), _field_info);
+  FieldLayoutBuilder lb(class_name(), loader_data(), super_klass(), _cp, /*_fields*/ _temp_field_info,
+      _parsed_annotations->is_contended(), is_inline_type(),
+      access_flags().is_abstract() && !access_flags().is_identity_class() && !access_flags().is_interface(),
+      _field_info, _inline_type_field_klasses);
   lb.build_layout();
+  if (is_inline_type()) {
+    _alignment = lb.get_alignment();
+    _first_field_offset = lb.get_first_field_offset();
+    _payload_size_in_bytes = lb.get_payload_size_in_byte();
+    _internal_null_marker_offset = lb.get_internal_null_marker_offset();
+  }
+  _has_inline_type_fields = _field_info->_has_inline_fields;
 
   int injected_fields_count = _temp_field_info->length() - _java_fields_count;
   _fieldinfo_stream =
     FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count,
                                             injected_fields_count, loader_data(), CHECK);
+
   _fields_status =
     MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(),
                                             FieldStatus(0), CHECK);
+  if (_field_info->_has_null_marker_offsets) {
+    int idx = 0;
+    _null_marker_offsets = MetadataFactory::new_array<int>(_loader_data, _temp_field_info->length(), 0, CHECK);
+    for (GrowableArrayIterator<FieldInfo> it = _temp_field_info->begin(); it != _temp_field_info->end(); ++it, ++idx) {
+      FieldInfo fieldinfo = *it;
+      if (fieldinfo.field_flags().has_null_marker()) {
+        assert(fieldinfo.null_marker_offset() != 0, "Invalid value");
+        _null_marker_offsets->at_put(idx, fieldinfo.null_marker_offset());
+      }
+    }
+  }
 }
 
 void ClassFileParser::set_klass(InstanceKlass* klass) {
 
 #ifdef ASSERT
