diff a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp
--- a/src/hotspot/share/prims/jni.cpp
+++ b/src/hotspot/share/prims/jni.cpp
@@ -53,10 +53,12 @@
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "nmt/memTracker.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/arrayOop.hpp"
+#include "oops/flatArrayOop.inline.hpp"
+#include "oops/inlineKlass.inline.hpp"
 #include "oops/instanceKlass.inline.hpp"
 #include "oops/instanceOop.hpp"
 #include "oops/klass.inline.hpp"
 #include "oops/markWord.hpp"
 #include "oops/method.hpp"
@@ -424,12 +426,13 @@
 
   // The slot is the index of the field description in the field-array
   // The jfieldID is the offset of the field within the object
   // It may also have hash bits for k, if VerifyJNIFields is turned on.
   int offset = InstanceKlass::cast(k1)->field_offset( slot );
+  bool is_flat = InstanceKlass::cast(k1)->field_is_flat(slot);
   assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
-  ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
+  ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_flat);
   return ret;
 JNI_END
 
 
 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
@@ -442,11 +445,11 @@
   DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
 
   methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
   assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
   oop reflection_method;
-  if (m->is_initializer()) {
+  if (m->is_object_constructor()) {
     reflection_method = Reflection::new_constructor(m, CHECK_NULL);
   } else {
     reflection_method = Reflection::new_method(m, false, CHECK_NULL);
   }
   ret = JNIHandles::make_local(THREAD, reflection_method);
@@ -800,11 +803,11 @@
     // float is coerced to double w/ va_arg
     case T_FLOAT:       push_float((jfloat) va_arg(_ap, jdouble)); break;
     case T_DOUBLE:      push_double(va_arg(_ap, jdouble)); break;
 
     case T_ARRAY:
-    case T_OBJECT:      push_object(va_arg(_ap, jobject)); break;
+    case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
     default:            ShouldNotReachHere();
     }
   }
 
  public:
@@ -840,11 +843,12 @@
     case T_BOOLEAN:     push_boolean((_ap++)->z); break;
     case T_LONG:        push_long((_ap++)->j); break;
     case T_FLOAT:       push_float((_ap++)->f); break;
     case T_DOUBLE:      push_double((_ap++)->d); break;
     case T_ARRAY:
-    case T_OBJECT:      push_object((_ap++)->l); break;
+    case T_OBJECT:
+    case T_PRIMITIVE_OBJECT: push_object((_ap++)->l); break;
     default:            ShouldNotReachHere();
     }
   }
 
  public:
@@ -967,11 +971,17 @@
   HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
 
   jobject ret = nullptr;
   DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
 
-  instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
+  oop clazzoop = JNIHandles::resolve_non_null(clazz);
+  Klass* k = java_lang_Class::as_Klass(clazzoop);
+  if (k == nullptr || k->is_inline_klass()) {
+    ResourceMark rm(THREAD);
+    THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
+  }
+  instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
   ret = JNIHandles::make_local(THREAD, i);
   return ret;
 JNI_END
 
 DT_RETURN_MARK_DECL(NewObjectA, jobject
@@ -981,17 +991,25 @@
   HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
 
   jobject obj = nullptr;
   DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
 
-  instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
+  oop clazzoop = JNIHandles::resolve_non_null(clazz);
+  Klass* k = java_lang_Class::as_Klass(clazzoop);
+  if (k == nullptr) {
+    ResourceMark rm(THREAD);
+    THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
+  }
+
+  instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
   obj = JNIHandles::make_local(THREAD, i);
   JavaValue jvalue(T_VOID);
   JNI_ArgumentPusherArray ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
+
   return obj;
-JNI_END
+  JNI_END
 
 
 DT_RETURN_MARK_DECL(NewObjectV, jobject
                     , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
 
@@ -999,15 +1017,23 @@
   HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
 
   jobject obj = nullptr;
   DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
 
-  instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
+  oop clazzoop = JNIHandles::resolve_non_null(clazz);
+  Klass* k = java_lang_Class::as_Klass(clazzoop);
+  if (k == nullptr) {
+    ResourceMark rm(THREAD);
+    THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
+  }
+
+  instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
   obj = JNIHandles::make_local(THREAD, i);
   JavaValue jvalue(T_VOID);
   JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
+
   return obj;
 JNI_END
 
 
 DT_RETURN_MARK_DECL(NewObject, jobject
@@ -1017,18 +1043,26 @@
   HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
 
   jobject obj = nullptr;
   DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
 
-  instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
+  oop clazzoop = JNIHandles::resolve_non_null(clazz);
+  Klass* k = java_lang_Class::as_Klass(clazzoop);
+  if (k == nullptr) {
+    ResourceMark rm(THREAD);
+    THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
+  }
+
+  instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
   obj = JNIHandles::make_local(THREAD, i);
   va_list args;
   va_start(args, methodID);
   JavaValue jvalue(T_VOID);
   JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
   va_end(args);
+
   return obj;
 JNI_END
 
 
 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
@@ -1775,27 +1809,38 @@
     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
   }
 
   // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
   // It may also have hash bits for k, if VerifyJNIFields is turned on.
-  ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
+  ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flat());
   return ret;
 JNI_END
 
 
 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
   HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
   oop o = JNIHandles::resolve_non_null(obj);
   Klass* k = o->klass();
   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
+  oop res = nullptr;
   // Keep JVMTI addition small and only check enabled flag here.
   // jni_GetField_probe() assumes that is okay to create handles.
   if (JvmtiExport::should_post_field_access()) {
     o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
   }
-  oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
-  jobject ret = JNIHandles::make_local(THREAD, loaded_obj);
+  if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
+    res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
+  } else {
+    assert(k->is_instance_klass(), "Only instance can have flat fields");
+    InstanceKlass* ik = InstanceKlass::cast(k);
+    fieldDescriptor fd;
+    ik->find_field_from_offset(offset, false, &fd);  // performance bottleneck
+    InstanceKlass* holder = fd.field_holder();
+    InlineKlass* field_vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
+    res = field_vklass->read_flat_field(o, ik->field_offset(fd.index()), CHECK_NULL);
+  }
+  jobject ret = JNIHandles::make_local(THREAD, res);
   HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
   return ret;
 JNI_END
 
 
@@ -1883,11 +1928,22 @@
   if (JvmtiExport::should_post_field_modification()) {
     jvalue field_value;
     field_value.l = value;
     o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
   }
-  HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
+  if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
+    HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
+  } else {
+    assert(k->is_instance_klass(), "Only instances can have flat fields");
+    InstanceKlass* ik = InstanceKlass::cast(k);
+    fieldDescriptor fd;
+    ik->find_field_from_offset(offset, false, &fd);
+    InstanceKlass* holder = fd.field_holder();
+    InlineKlass* vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
+    oop v = JNIHandles::resolve_non_null(value);
+    vklass->write_flat_field(o, offset, v, CHECK);
+  }
   HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
 JNI_END
 
 // TODO: make this a template
 
@@ -2299,53 +2355,91 @@
 
 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
  HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
   jobject ret = nullptr;
   DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
-  objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
-  if (a->is_within_bounds(index)) {
-    ret = JNIHandles::make_local(THREAD, a->obj_at(index));
-    return ret;
+  oop res = nullptr;
+  arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
+  if (arr->is_within_bounds(index)) {
+    if (arr->is_flatArray()) {
+      flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
+      flatArrayHandle vah(thread, a);
+      res = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK_NULL);
+      assert(res != nullptr, "Must be set in one of two paths above");
+    } else {
+      assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
+      objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
+      res = a->obj_at(index);
+    }
   } else {
     ResourceMark rm(THREAD);
     stringStream ss;
-    ss.print("Index %d out of bounds for length %d", index, a->length());
+    ss.print("Index %d out of bounds for length %d", index,arr->length());
     THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
   }
+  ret = JNIHandles::make_local(THREAD, res);
+  return ret;
 JNI_END
 
 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
                          , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
 
 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
  HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
   DT_VOID_RETURN_MARK(SetObjectArrayElement);
 
-  objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
-  oop v = JNIHandles::resolve(value);
-  if (a->is_within_bounds(index)) {
-    if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
-      a->obj_at_put(index, v);
-    } else {
-      ResourceMark rm(THREAD);
-      stringStream ss;
-      Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
-      ss.print("type mismatch: can not store %s to %s[%d]",
-               v->klass()->external_name(),
-               bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
-               index);
-      for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
-        ss.print("[]");
-      }
-      THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
-    }
-  } else {
-    ResourceMark rm(THREAD);
-    stringStream ss;
-    ss.print("Index %d out of bounds for length %d", index, a->length());
-    THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
-  }
+   bool oob = false;
+   int length = -1;
+   oop res = nullptr;
+   arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
+   if (arr->is_within_bounds(index)) {
+     if (arr->is_flatArray()) {
+       flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
+       oop v = JNIHandles::resolve(value);
+       FlatArrayKlass* vaklass = FlatArrayKlass::cast(a->klass());
+       InlineKlass* element_vklass = vaklass->element_klass();
+       if (v != nullptr && v->is_a(element_vklass)) {
+         a->value_copy_to_index(v, index);
+       } else {
+         ResourceMark rm(THREAD);
+         stringStream ss;
+         Klass *kl = FlatArrayKlass::cast(a->klass());
+         ss.print("type mismatch: can not store %s to %s[%d]",
+             v->klass()->external_name(),
+             kl->external_name(),
+             index);
+         for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
+           ss.print("[]");
+         }
+         THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
+       }
+     } else {
+       assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
+       objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
+       oop v = JNIHandles::resolve(value);
+       if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
+         a->obj_at_put(index, v);
+       } else {
+         ResourceMark rm(THREAD);
+         stringStream ss;
+         Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
+         ss.print("type mismatch: can not store %s to %s[%d]",
+             v->klass()->external_name(),
+             bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
+                 index);
+         for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
+           ss.print("[]");
+         }
+         THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
+       }
+     }
+   } else {
+     ResourceMark rm(THREAD);
+     stringStream ss;
+     ss.print("Index %d out of bounds for length %d", index, arr->length());
+     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
+   }
 JNI_END
 
 
 
 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
