< prev index next >

src/hotspot/share/prims/jni.cpp

Print this page
*** 24,10 ***
--- 24,11 ---
   *
   */
  
  #include "precompiled.hpp"
  #include "jni.h"
+ #include "jni.h"
  #include "jvm.h"
  #include "ci/ciReplay.hpp"
  #include "classfile/altHashing.hpp"
  #include "classfile/classFileStream.hpp"
  #include "classfile/classLoader.hpp"

*** 54,10 ***
--- 55,12 ---
  #include "memory/oopFactory.hpp"
  #include "memory/resourceArea.hpp"
  #include "memory/universe.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"

*** 420,12 ***
  
    // 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.
    intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
    assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
!   ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
    return ret;
  JNI_END
  
  
  DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
--- 423,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.
    intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
+   bool is_inlined = InstanceKlass::cast(k1)->field_is_inlined(slot);
    assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
!   ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_inlined);
    return ret;
  JNI_END
  
  
  DT_RETURN_MARK_DECL(ToReflectedMethod, jobject

*** 438,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()) {
      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);
--- 442,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_object_constructor() || m->is_static_init_factory()) {
      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);

*** 494,13 ***
      return ret;
    }
    Klass* sub_klass   = java_lang_Class::as_Klass(sub_mirror);
    Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
    assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");
!   jboolean ret = sub_klass->is_subtype_of(super_klass) ?
!                    JNI_TRUE : JNI_FALSE;
! 
    HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
    return ret;
  JNI_END
  
  
--- 498,22 ---
      return ret;
    }
    Klass* sub_klass   = java_lang_Class::as_Klass(sub_mirror);
    Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
    assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");
!   jboolean ret;
!   if (sub_klass == super_klass && sub_klass->is_inline_klass()) {
!     // val type is a subtype of ref type
+     InlineKlass* ik = InlineKlass::cast(sub_klass);
+     if (sub_mirror == super_mirror || (ik->val_mirror() == sub_mirror && ik->ref_mirror() == super_mirror)) {
+       ret = JNI_TRUE;
+     } else {
+       ret = JNI_FALSE;
+     }
+   } else {
+     ret = sub_klass->is_subtype_of(super_klass) ? JNI_TRUE : JNI_FALSE;
+   }
    HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
    return ret;
  JNI_END
  
  

*** 801,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;
      default:            ShouldNotReachHere();
      }
    }
  
   public:
--- 814,12 ---
      // 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:
+     case T_INLINE_TYPE: push_object(va_arg(_ap, jobject)); break;
      default:            ShouldNotReachHere();
      }
    }
  
   public:

*** 841,11 ***
      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;
      default:            ShouldNotReachHere();
      }
    }
  
   public:
--- 855,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:
+     case T_INLINE_TYPE: push_object((_ap++)->l); break;
      default:            ShouldNotReachHere();
      }
    }
  
   public:

*** 977,17 ***
    HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
  
    jobject obj = NULL;
    DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
  
!   instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), 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
  
  
  DT_RETURN_MARK_DECL(NewObjectV, jobject
                      , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
  
--- 992,31 ---
    HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
  
    jobject obj = NULL;
    DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
  
!   oop clazzoop = JNIHandles::resolve_non_null(clazz);
!   Klass* k = java_lang_Class::as_Klass(clazzoop);
!   if (k == NULL) {
!     ResourceMark rm(THREAD);
!     THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
+   }
+ 
+   if (!k->is_inline_klass()) {
+     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);
+   } else {
+     JavaValue jvalue(T_INLINE_TYPE);
+     JNI_ArgumentPusherArray ap(methodID, args);
+     jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_NULL);
+     obj = jvalue.get_jobject();
+   }
    return obj;
!   JNI_END
  
  
  DT_RETURN_MARK_DECL(NewObjectV, jobject
                      , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
  

*** 995,15 ***
    HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
  
    jobject obj = NULL;
    DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
  
!   instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), 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
--- 1024,29 ---
    HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
  
    jobject obj = NULL;
    DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
  
!   oop clazzoop = JNIHandles::resolve_non_null(clazz);
!   Klass* k = java_lang_Class::as_Klass(clazzoop);
!   if (k == NULL) {
!     ResourceMark rm(THREAD);
!     THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
+   }
+ 
+   if (!k->is_inline_klass()) {
+     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);
+   } else {
+     JavaValue jvalue(T_INLINE_TYPE);
+     JNI_ArgumentPusherVaArg ap(methodID, args);
+     jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_NULL);
+     obj = jvalue.get_jobject();
+   }
    return obj;
  JNI_END
  
  
  DT_RETURN_MARK_DECL(NewObject, jobject

*** 1013,18 ***
    HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
  
    jobject obj = NULL;
    DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
  
!   instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), 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))
--- 1056,35 ---
    HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
  
    jobject obj = NULL;
    DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
  
!   oop clazzoop = JNIHandles::resolve_non_null(clazz);
!   Klass* k = java_lang_Class::as_Klass(clazzoop);
!   if (k == NULL) {
!     ResourceMark rm(THREAD);
!     THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
!   }
! 
!   if (!k->is_inline_klass()) {
+     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);
+   } else {
+     va_list args;
+     va_start(args, methodID);
+     JavaValue jvalue(T_INLINE_TYPE);
+     JNI_ArgumentPusherVaArg ap(methodID, args);
+     jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_NULL);
+     va_end(args);
+     obj = jvalue.get_jobject();
+   }
    return obj;
  JNI_END
  
  
  JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))

*** 1771,27 ***
      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());
    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);
    // 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);
    HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
    return ret;
  JNI_END
  
  
--- 1831,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(), fd.is_inlined());
    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 = NULL;
    // 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);
    }
!   if (!jfieldIDWorkaround::is_inlined_jfieldID(fieldID)) {
!     res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
+   } else {
+     assert(k->is_instance_klass(), "Only instance can have inlined 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_inlined_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
  
  

*** 1879,11 ***
    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));
    HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
  JNI_END
  
  
  #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
--- 1950,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);
    }
!   if (!jfieldIDWorkaround::is_inlined_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 inlined 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_inlined_field(o, offset, v, CHECK);
+   }
    HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
  JNI_END
  
  
  #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \

*** 2296,53 ***
  
  JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
   HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
    jobject ret = NULL;
    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;
    } else {
      ResourceMark rm(THREAD);
      stringStream ss;
!     ss.print("Index %d out of bounds for length %d", index, a->length());
      THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
    }
  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 == NULL || 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());
!   }
  JNI_END
  
  
  
  #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
--- 2378,91 ---
  
  JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
   HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
    jobject ret = NULL;
    DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
!   oop res = NULL;
!   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 != NULL, "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,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);
  
!    bool oob = false;
!    int length = -1;
!    oop res = NULL;
!    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 != NULL && 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 == NULL || 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 \

*** 3134,11 ***
  
  JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
    return Modules::get_module(clazz, THREAD);
  JNI_END
  
- 
  // Structure containing all jni functions
  struct JNINativeInterface_ jni_NativeInterface = {
      NULL,
      NULL,
      NULL,
--- 3254,10 ---

*** 3418,11 ***
  
      jni_GetObjectRefType,
  
      // Module features
  
!     jni_GetModule
  };
  
  
  // For jvmti use to modify jni function table.
  // Java threads in native contiues to run until it is transitioned
--- 3537,12 ---
  
      jni_GetObjectRefType,
  
      // Module features
  
!     jni_GetModule,
+ 
  };
  
  
  // For jvmti use to modify jni function table.
  // Java threads in native contiues to run until it is transitioned
< prev index next >