37 #include "classfile/modules.hpp"
38 #include "classfile/symbolTable.hpp"
39 #include "classfile/systemDictionary.hpp"
40 #include "classfile/vmClasses.hpp"
41 #include "classfile/vmSymbols.hpp"
42 #include "compiler/compiler_globals.hpp"
43 #include "gc/shared/collectedHeap.hpp"
44 #include "gc/shared/gcLocker.inline.hpp"
45 #include "gc/shared/stringdedup/stringDedup.hpp"
46 #include "interpreter/linkResolver.hpp"
47 #include "jni.h"
48 #include "jvm.h"
49 #include "logging/log.hpp"
50 #include "memory/allocation.hpp"
51 #include "memory/allocation.inline.hpp"
52 #include "memory/oopFactory.hpp"
53 #include "memory/resourceArea.hpp"
54 #include "memory/universe.hpp"
55 #include "oops/access.inline.hpp"
56 #include "oops/arrayOop.hpp"
57 #include "oops/instanceKlass.inline.hpp"
58 #include "oops/instanceOop.hpp"
59 #include "oops/klass.inline.hpp"
60 #include "oops/markWord.hpp"
61 #include "oops/method.hpp"
62 #include "oops/objArrayKlass.hpp"
63 #include "oops/objArrayOop.inline.hpp"
64 #include "oops/oop.inline.hpp"
65 #include "oops/symbol.hpp"
66 #include "oops/typeArrayKlass.hpp"
67 #include "oops/typeArrayOop.inline.hpp"
68 #include "prims/jniCheck.hpp"
69 #include "prims/jniExport.hpp"
70 #include "prims/jniFastGetField.hpp"
71 #include "prims/jvm_misc.hpp"
72 #include "prims/jvmtiExport.hpp"
73 #include "prims/jvmtiThreadState.hpp"
74 #include "runtime/arguments.hpp"
75 #include "runtime/atomic.hpp"
76 #include "runtime/fieldDescriptor.inline.hpp"
409 int modifiers = java_lang_reflect_Field::modifiers(reflected);
410
411 // Make sure class is initialized before handing id's out to fields
412 k1->initialize(CHECK_NULL);
413
414 // First check if this is a static field
415 if (modifiers & JVM_ACC_STATIC) {
416 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
417 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
418 assert(id != nullptr, "corrupt Field object");
419 debug_only(id->set_is_static_field_id();)
420 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
421 ret = jfieldIDWorkaround::to_static_jfieldID(id);
422 return ret;
423 }
424
425 // The slot is the index of the field description in the field-array
426 // The jfieldID is the offset of the field within the object
427 // It may also have hash bits for k, if VerifyJNIFields is turned on.
428 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
429 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
430 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
431 return ret;
432 JNI_END
433
434
435 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
436 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
437
438 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
439 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
440
441 jobject ret = nullptr;
442 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
443
444 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
445 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
446 oop reflection_method;
447 if (m->is_initializer()) {
448 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
449 } else {
450 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
451 }
452 ret = JNIHandles::make_local(THREAD, reflection_method);
453 return ret;
454 JNI_END
455
456 DT_RETURN_MARK_DECL(GetSuperclass, jclass
457 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
458
459 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
460 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
461
462 jclass obj = nullptr;
463 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
464
465 oop mirror = JNIHandles::resolve_non_null(sub);
466 // primitive classes return null
467 if (java_lang_Class::is_primitive(mirror)) return nullptr;
483 "java_super computation depends on interface, array, other super");
484 obj = (super == nullptr) ? nullptr : (jclass) JNIHandles::make_local(THREAD, super->java_mirror());
485 return obj;
486 JNI_END
487
488 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super))
489 HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(env, sub, super);
490
491 oop sub_mirror = JNIHandles::resolve_non_null(sub);
492 oop super_mirror = JNIHandles::resolve_non_null(super);
493 if (java_lang_Class::is_primitive(sub_mirror) ||
494 java_lang_Class::is_primitive(super_mirror)) {
495 jboolean ret = (sub_mirror == super_mirror);
496
497 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
498 return ret;
499 }
500 Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);
501 Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
502 assert(sub_klass != nullptr && super_klass != nullptr, "invalid arguments to jni_IsAssignableFrom");
503 jboolean ret = sub_klass->is_subtype_of(super_klass) ?
504 JNI_TRUE : JNI_FALSE;
505
506 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
507 return ret;
508 JNI_END
509
510
511 DT_RETURN_MARK_DECL(Throw, jint
512 , HOTSPOT_JNI_THROW_RETURN(_ret_ref));
513
514 JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))
515 HOTSPOT_JNI_THROW_ENTRY(env, obj);
516
517 jint ret = JNI_OK;
518 DT_RETURN_MARK(Throw, jint, (const jint&)ret);
519
520 THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);
521 ShouldNotReachHere();
522 return 0; // Mute compiler.
523 JNI_END
524
525
785 }
786
787 friend class SignatureIterator; // so do_parameters_on can call do_type
788 void do_type(BasicType type) {
789 switch (type) {
790 // these are coerced to int when using va_arg
791 case T_BYTE:
792 case T_CHAR:
793 case T_SHORT:
794 case T_INT: push_int(va_arg(_ap, jint)); break;
795 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
796
797 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
798
799 case T_LONG: push_long(va_arg(_ap, jlong)); break;
800 // float is coerced to double w/ va_arg
801 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
802 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
803
804 case T_ARRAY:
805 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
806 default: ShouldNotReachHere();
807 }
808 }
809
810 public:
811 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
812 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
813 set_ap(rap);
814 }
815
816 ~JNI_ArgumentPusherVaArg() {
817 va_end(_ap);
818 }
819
820 virtual void push_arguments_on(JavaCallArguments* arguments) {
821 _arguments = arguments;
822 do_parameters_on(this);
823 }
824 };
825
826
827 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
828 protected:
829 const jvalue *_ap;
830
831 inline void set_ap(const jvalue *rap) { _ap = rap; }
832
833 friend class SignatureIterator; // so do_parameters_on can call do_type
834 void do_type(BasicType type) {
835 switch (type) {
836 case T_CHAR: push_int((_ap++)->c); break;
837 case T_SHORT: push_int((_ap++)->s); break;
838 case T_BYTE: push_int((_ap++)->b); break;
839 case T_INT: push_int((_ap++)->i); break;
840 case T_BOOLEAN: push_boolean((_ap++)->z); break;
841 case T_LONG: push_long((_ap++)->j); break;
842 case T_FLOAT: push_float((_ap++)->f); break;
843 case T_DOUBLE: push_double((_ap++)->d); break;
844 case T_ARRAY:
845 case T_OBJECT: push_object((_ap++)->l); break;
846 default: ShouldNotReachHere();
847 }
848 }
849
850 public:
851 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
852 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
853 set_ap(rap);
854 }
855
856 virtual void push_arguments_on(JavaCallArguments* arguments) {
857 _arguments = arguments;
858 do_parameters_on(this);
859 }
860 };
861
862
863 enum JNICallType {
864 JNI_STATIC,
865 JNI_VIRTUAL,
961 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
962 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
963
964 jobject ret = nullptr;
965 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
966
967 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
968 ret = JNIHandles::make_local(THREAD, i);
969 return ret;
970 JNI_END
971
972 DT_RETURN_MARK_DECL(NewObjectA, jobject
973 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
974
975 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
976 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
977
978 jobject obj = nullptr;
979 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
980
981 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
982 obj = JNIHandles::make_local(THREAD, i);
983 JavaValue jvalue(T_VOID);
984 JNI_ArgumentPusherArray ap(methodID, args);
985 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
986 return obj;
987 JNI_END
988
989
990 DT_RETURN_MARK_DECL(NewObjectV, jobject
991 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
992
993 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
994 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
995
996 jobject obj = nullptr;
997 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
998
999 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
1000 obj = JNIHandles::make_local(THREAD, i);
1001 JavaValue jvalue(T_VOID);
1002 JNI_ArgumentPusherVaArg ap(methodID, args);
1003 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1004 return obj;
1005 JNI_END
1006
1007
1008 DT_RETURN_MARK_DECL(NewObject, jobject
1009 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1010
1011 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1012 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1013
1014 jobject obj = nullptr;
1015 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1016
1017 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
1018 obj = JNIHandles::make_local(THREAD, i);
1019 va_list args;
1020 va_start(args, methodID);
1021 JavaValue jvalue(T_VOID);
1022 JNI_ArgumentPusherVaArg ap(methodID, args);
1023 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1024 va_end(args);
1025 return obj;
1026 JNI_END
1027
1028
1029 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1030 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1031
1032 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1033 jclass ret =
1034 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1035
1036 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1037 return ret;
1038 JNI_END
1039
1040 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1041 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1042
1043 jboolean ret = JNI_TRUE;
1044 if (obj != nullptr) {
1755 // table. If they're not there, the field doesn't exist.
1756 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1757 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1758 if (fieldname == nullptr || signame == nullptr) {
1759 ResourceMark rm;
1760 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1761 }
1762
1763 // Make sure class is initialized before handing id's out to fields
1764 k->initialize(CHECK_NULL);
1765
1766 fieldDescriptor fd;
1767 if (!k->is_instance_klass() ||
1768 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1769 ResourceMark rm;
1770 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1771 }
1772
1773 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1774 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1775 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
1776 return ret;
1777 JNI_END
1778
1779
1780 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1781 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1782 oop o = JNIHandles::resolve_non_null(obj);
1783 Klass* k = o->klass();
1784 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1785 // Keep JVMTI addition small and only check enabled flag here.
1786 // jni_GetField_probe() assumes that is okay to create handles.
1787 if (JvmtiExport::should_post_field_access()) {
1788 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1789 }
1790 oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1791 jobject ret = JNIHandles::make_local(THREAD, loaded_obj);
1792 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1793 return ret;
1794 JNI_END
1795
1796
1797
1798 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1799 , EntryProbe, ReturnProbe) \
1800 \
1801 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1802 , ReturnProbe); \
1803 \
1804 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1805 \
1806 EntryProbe; \
1807 Return ret = 0;\
1808 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1809 \
1810 oop o = JNIHandles::resolve_non_null(obj); \
1811 Klass* k = o->klass(); \
1863 return (address)jni_GetLongField;
1864 }
1865 address jni_GetFloatField_addr() {
1866 return (address)jni_GetFloatField;
1867 }
1868 address jni_GetDoubleField_addr() {
1869 return (address)jni_GetDoubleField;
1870 }
1871
1872 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1873 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1874 oop o = JNIHandles::resolve_non_null(obj);
1875 Klass* k = o->klass();
1876 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1877 // Keep JVMTI addition small and only check enabled flag here.
1878 if (JvmtiExport::should_post_field_modification()) {
1879 jvalue field_value;
1880 field_value.l = value;
1881 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1882 }
1883 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1884 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1885 JNI_END
1886
1887
1888 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1889 , EntryProbe, ReturnProbe) \
1890 \
1891 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1892 \
1893 EntryProbe; \
1894 \
1895 oop o = JNIHandles::resolve_non_null(obj); \
1896 Klass* k = o->klass(); \
1897 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1898 /* Keep JVMTI addition small and only check enabled flag here. */ \
1899 if (JvmtiExport::should_post_field_modification()) { \
1900 jvalue field_value; \
1901 field_value.unionType = value; \
1902 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
1903 } \
2280 Klass* ak = ek->array_klass(CHECK_NULL);
2281 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2282 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2283 oop initial_value = JNIHandles::resolve(initialElement);
2284 if (initial_value != nullptr) { // array already initialized with null
2285 for (int index = 0; index < length; index++) {
2286 result->obj_at_put(index, initial_value);
2287 }
2288 }
2289 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2290 return ret;
2291 JNI_END
2292
2293 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2294 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2295
2296 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2297 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2298 jobject ret = nullptr;
2299 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2300 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2301 if (a->is_within_bounds(index)) {
2302 ret = JNIHandles::make_local(THREAD, a->obj_at(index));
2303 return ret;
2304 } else {
2305 ResourceMark rm(THREAD);
2306 stringStream ss;
2307 ss.print("Index %d out of bounds for length %d", index, a->length());
2308 THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2309 }
2310 JNI_END
2311
2312 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2313 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2314
2315 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2316 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2317 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2318
2319 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2320 oop v = JNIHandles::resolve(value);
2321 if (a->is_within_bounds(index)) {
2322 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2323 a->obj_at_put(index, v);
2324 } else {
2325 ResourceMark rm(THREAD);
2326 stringStream ss;
2327 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2328 ss.print("type mismatch: can not store %s to %s[%d]",
2329 v->klass()->external_name(),
2330 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2331 index);
2332 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2333 ss.print("[]");
2334 }
2335 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2336 }
2337 } else {
2338 ResourceMark rm(THREAD);
2339 stringStream ss;
2340 ss.print("Index %d out of bounds for length %d", index, a->length());
2341 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2342 }
2343 JNI_END
2344
2345
2346
2347 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2348 ,EntryProbe,ReturnProbe) \
2349 \
2350 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2351 , ReturnProbe); \
2352 \
2353 JNI_ENTRY(Return, \
2354 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2355 EntryProbe; \
2356 Return ret = nullptr;\
2357 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2358 \
2359 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2360 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2361 return ret;\
2362 JNI_END
|
37 #include "classfile/modules.hpp"
38 #include "classfile/symbolTable.hpp"
39 #include "classfile/systemDictionary.hpp"
40 #include "classfile/vmClasses.hpp"
41 #include "classfile/vmSymbols.hpp"
42 #include "compiler/compiler_globals.hpp"
43 #include "gc/shared/collectedHeap.hpp"
44 #include "gc/shared/gcLocker.inline.hpp"
45 #include "gc/shared/stringdedup/stringDedup.hpp"
46 #include "interpreter/linkResolver.hpp"
47 #include "jni.h"
48 #include "jvm.h"
49 #include "logging/log.hpp"
50 #include "memory/allocation.hpp"
51 #include "memory/allocation.inline.hpp"
52 #include "memory/oopFactory.hpp"
53 #include "memory/resourceArea.hpp"
54 #include "memory/universe.hpp"
55 #include "oops/access.inline.hpp"
56 #include "oops/arrayOop.hpp"
57 #include "oops/flatArrayOop.inline.hpp"
58 #include "oops/inlineKlass.inline.hpp"
59 #include "oops/instanceKlass.inline.hpp"
60 #include "oops/instanceOop.hpp"
61 #include "oops/klass.inline.hpp"
62 #include "oops/markWord.hpp"
63 #include "oops/method.hpp"
64 #include "oops/objArrayKlass.hpp"
65 #include "oops/objArrayOop.inline.hpp"
66 #include "oops/oop.inline.hpp"
67 #include "oops/symbol.hpp"
68 #include "oops/typeArrayKlass.hpp"
69 #include "oops/typeArrayOop.inline.hpp"
70 #include "prims/jniCheck.hpp"
71 #include "prims/jniExport.hpp"
72 #include "prims/jniFastGetField.hpp"
73 #include "prims/jvm_misc.hpp"
74 #include "prims/jvmtiExport.hpp"
75 #include "prims/jvmtiThreadState.hpp"
76 #include "runtime/arguments.hpp"
77 #include "runtime/atomic.hpp"
78 #include "runtime/fieldDescriptor.inline.hpp"
411 int modifiers = java_lang_reflect_Field::modifiers(reflected);
412
413 // Make sure class is initialized before handing id's out to fields
414 k1->initialize(CHECK_NULL);
415
416 // First check if this is a static field
417 if (modifiers & JVM_ACC_STATIC) {
418 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
419 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
420 assert(id != nullptr, "corrupt Field object");
421 debug_only(id->set_is_static_field_id();)
422 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
423 ret = jfieldIDWorkaround::to_static_jfieldID(id);
424 return ret;
425 }
426
427 // The slot is the index of the field description in the field-array
428 // The jfieldID is the offset of the field within the object
429 // It may also have hash bits for k, if VerifyJNIFields is turned on.
430 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
431 bool is_flat = InstanceKlass::cast(k1)->field_is_flat(slot);
432 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
433 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_flat);
434 return ret;
435 JNI_END
436
437
438 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
439 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
440
441 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
442 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
443
444 jobject ret = nullptr;
445 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
446
447 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
448 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
449 oop reflection_method;
450 if (m->is_object_constructor() || m->is_static_vnew_factory()) {
451 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
452 } else {
453 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
454 }
455 ret = JNIHandles::make_local(THREAD, reflection_method);
456 return ret;
457 JNI_END
458
459 DT_RETURN_MARK_DECL(GetSuperclass, jclass
460 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
461
462 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
463 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
464
465 jclass obj = nullptr;
466 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
467
468 oop mirror = JNIHandles::resolve_non_null(sub);
469 // primitive classes return null
470 if (java_lang_Class::is_primitive(mirror)) return nullptr;
486 "java_super computation depends on interface, array, other super");
487 obj = (super == nullptr) ? nullptr : (jclass) JNIHandles::make_local(THREAD, super->java_mirror());
488 return obj;
489 JNI_END
490
491 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super))
492 HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(env, sub, super);
493
494 oop sub_mirror = JNIHandles::resolve_non_null(sub);
495 oop super_mirror = JNIHandles::resolve_non_null(super);
496 if (java_lang_Class::is_primitive(sub_mirror) ||
497 java_lang_Class::is_primitive(super_mirror)) {
498 jboolean ret = (sub_mirror == super_mirror);
499
500 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
501 return ret;
502 }
503 Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);
504 Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
505 assert(sub_klass != nullptr && super_klass != nullptr, "invalid arguments to jni_IsAssignableFrom");
506 jboolean ret;
507 if (sub_klass == super_klass && sub_klass->is_inline_klass()) {
508 // val type is a subtype of ref type
509 InlineKlass* ik = InlineKlass::cast(sub_klass);
510 if (sub_mirror == super_mirror || (ik->val_mirror() == sub_mirror && ik->ref_mirror() == super_mirror)) {
511 ret = JNI_TRUE;
512 } else {
513 ret = JNI_FALSE;
514 }
515 } else {
516 ret = sub_klass->is_subtype_of(super_klass) ? JNI_TRUE : JNI_FALSE;
517 }
518 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
519 return ret;
520 JNI_END
521
522
523 DT_RETURN_MARK_DECL(Throw, jint
524 , HOTSPOT_JNI_THROW_RETURN(_ret_ref));
525
526 JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))
527 HOTSPOT_JNI_THROW_ENTRY(env, obj);
528
529 jint ret = JNI_OK;
530 DT_RETURN_MARK(Throw, jint, (const jint&)ret);
531
532 THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);
533 ShouldNotReachHere();
534 return 0; // Mute compiler.
535 JNI_END
536
537
797 }
798
799 friend class SignatureIterator; // so do_parameters_on can call do_type
800 void do_type(BasicType type) {
801 switch (type) {
802 // these are coerced to int when using va_arg
803 case T_BYTE:
804 case T_CHAR:
805 case T_SHORT:
806 case T_INT: push_int(va_arg(_ap, jint)); break;
807 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
808
809 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
810
811 case T_LONG: push_long(va_arg(_ap, jlong)); break;
812 // float is coerced to double w/ va_arg
813 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
814 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
815
816 case T_ARRAY:
817 case T_OBJECT:
818 case T_PRIMITIVE_OBJECT: push_object(va_arg(_ap, jobject)); break;
819 default: ShouldNotReachHere();
820 }
821 }
822
823 public:
824 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
825 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
826 set_ap(rap);
827 }
828
829 ~JNI_ArgumentPusherVaArg() {
830 va_end(_ap);
831 }
832
833 virtual void push_arguments_on(JavaCallArguments* arguments) {
834 _arguments = arguments;
835 do_parameters_on(this);
836 }
837 };
838
839
840 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
841 protected:
842 const jvalue *_ap;
843
844 inline void set_ap(const jvalue *rap) { _ap = rap; }
845
846 friend class SignatureIterator; // so do_parameters_on can call do_type
847 void do_type(BasicType type) {
848 switch (type) {
849 case T_CHAR: push_int((_ap++)->c); break;
850 case T_SHORT: push_int((_ap++)->s); break;
851 case T_BYTE: push_int((_ap++)->b); break;
852 case T_INT: push_int((_ap++)->i); break;
853 case T_BOOLEAN: push_boolean((_ap++)->z); break;
854 case T_LONG: push_long((_ap++)->j); break;
855 case T_FLOAT: push_float((_ap++)->f); break;
856 case T_DOUBLE: push_double((_ap++)->d); break;
857 case T_ARRAY:
858 case T_OBJECT:
859 case T_PRIMITIVE_OBJECT: push_object((_ap++)->l); break;
860 default: ShouldNotReachHere();
861 }
862 }
863
864 public:
865 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
866 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
867 set_ap(rap);
868 }
869
870 virtual void push_arguments_on(JavaCallArguments* arguments) {
871 _arguments = arguments;
872 do_parameters_on(this);
873 }
874 };
875
876
877 enum JNICallType {
878 JNI_STATIC,
879 JNI_VIRTUAL,
975 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
976 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
977
978 jobject ret = nullptr;
979 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
980
981 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
982 ret = JNIHandles::make_local(THREAD, i);
983 return ret;
984 JNI_END
985
986 DT_RETURN_MARK_DECL(NewObjectA, jobject
987 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
988
989 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
990 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
991
992 jobject obj = nullptr;
993 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
994
995 oop clazzoop = JNIHandles::resolve_non_null(clazz);
996 Klass* k = java_lang_Class::as_Klass(clazzoop);
997 if (k == nullptr) {
998 ResourceMark rm(THREAD);
999 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1000 }
1001
1002 if (!k->is_inline_klass()) {
1003 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1004 obj = JNIHandles::make_local(THREAD, i);
1005 JavaValue jvalue(T_VOID);
1006 JNI_ArgumentPusherArray ap(methodID, args);
1007 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1008 } else {
1009 JavaValue jvalue(T_PRIMITIVE_OBJECT);
1010 JNI_ArgumentPusherArray ap(methodID, args);
1011 jni_invoke_static(env, &jvalue, nullptr, JNI_STATIC, methodID, &ap, CHECK_NULL);
1012 obj = jvalue.get_jobject();
1013 }
1014 return obj;
1015 JNI_END
1016
1017
1018 DT_RETURN_MARK_DECL(NewObjectV, jobject
1019 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
1020
1021 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
1022 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
1023
1024 jobject obj = nullptr;
1025 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
1026
1027 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1028 Klass* k = java_lang_Class::as_Klass(clazzoop);
1029 if (k == nullptr) {
1030 ResourceMark rm(THREAD);
1031 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1032 }
1033
1034 if (!k->is_inline_klass()) {
1035 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1036 obj = JNIHandles::make_local(THREAD, i);
1037 JavaValue jvalue(T_VOID);
1038 JNI_ArgumentPusherVaArg ap(methodID, args);
1039 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1040 } else {
1041 JavaValue jvalue(T_PRIMITIVE_OBJECT);
1042 JNI_ArgumentPusherVaArg ap(methodID, args);
1043 jni_invoke_static(env, &jvalue, nullptr, JNI_STATIC, methodID, &ap, CHECK_NULL);
1044 obj = jvalue.get_jobject();
1045 }
1046 return obj;
1047 JNI_END
1048
1049
1050 DT_RETURN_MARK_DECL(NewObject, jobject
1051 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1052
1053 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1054 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1055
1056 jobject obj = nullptr;
1057 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1058
1059 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1060 Klass* k = java_lang_Class::as_Klass(clazzoop);
1061 if (k == nullptr) {
1062 ResourceMark rm(THREAD);
1063 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1064 }
1065
1066 if (!k->is_inline_klass()) {
1067 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1068 obj = JNIHandles::make_local(THREAD, i);
1069 va_list args;
1070 va_start(args, methodID);
1071 JavaValue jvalue(T_VOID);
1072 JNI_ArgumentPusherVaArg ap(methodID, args);
1073 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1074 va_end(args);
1075 } else {
1076 va_list args;
1077 va_start(args, methodID);
1078 JavaValue jvalue(T_PRIMITIVE_OBJECT);
1079 JNI_ArgumentPusherVaArg ap(methodID, args);
1080 jni_invoke_static(env, &jvalue, nullptr, JNI_STATIC, methodID, &ap, CHECK_NULL);
1081 va_end(args);
1082 obj = jvalue.get_jobject();
1083 }
1084 return obj;
1085 JNI_END
1086
1087
1088 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1089 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1090
1091 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1092 jclass ret =
1093 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1094
1095 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1096 return ret;
1097 JNI_END
1098
1099 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1100 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1101
1102 jboolean ret = JNI_TRUE;
1103 if (obj != nullptr) {
1814 // table. If they're not there, the field doesn't exist.
1815 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1816 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1817 if (fieldname == nullptr || signame == nullptr) {
1818 ResourceMark rm;
1819 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1820 }
1821
1822 // Make sure class is initialized before handing id's out to fields
1823 k->initialize(CHECK_NULL);
1824
1825 fieldDescriptor fd;
1826 if (!k->is_instance_klass() ||
1827 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1828 ResourceMark rm;
1829 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1830 }
1831
1832 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1833 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1834 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flat());
1835 return ret;
1836 JNI_END
1837
1838
1839 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1840 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1841 oop o = JNIHandles::resolve_non_null(obj);
1842 Klass* k = o->klass();
1843 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1844 oop res = nullptr;
1845 // Keep JVMTI addition small and only check enabled flag here.
1846 // jni_GetField_probe() assumes that is okay to create handles.
1847 if (JvmtiExport::should_post_field_access()) {
1848 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1849 }
1850 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1851 res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1852 } else {
1853 assert(k->is_instance_klass(), "Only instance can have flat fields");
1854 InstanceKlass* ik = InstanceKlass::cast(k);
1855 fieldDescriptor fd;
1856 ik->find_field_from_offset(offset, false, &fd); // performance bottleneck
1857 InstanceKlass* holder = fd.field_holder();
1858 InlineKlass* field_vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
1859 res = field_vklass->read_flat_field(o, ik->field_offset(fd.index()), CHECK_NULL);
1860 }
1861 jobject ret = JNIHandles::make_local(THREAD, res);
1862 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1863 return ret;
1864 JNI_END
1865
1866
1867
1868 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1869 , EntryProbe, ReturnProbe) \
1870 \
1871 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1872 , ReturnProbe); \
1873 \
1874 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1875 \
1876 EntryProbe; \
1877 Return ret = 0;\
1878 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1879 \
1880 oop o = JNIHandles::resolve_non_null(obj); \
1881 Klass* k = o->klass(); \
1933 return (address)jni_GetLongField;
1934 }
1935 address jni_GetFloatField_addr() {
1936 return (address)jni_GetFloatField;
1937 }
1938 address jni_GetDoubleField_addr() {
1939 return (address)jni_GetDoubleField;
1940 }
1941
1942 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1943 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1944 oop o = JNIHandles::resolve_non_null(obj);
1945 Klass* k = o->klass();
1946 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1947 // Keep JVMTI addition small and only check enabled flag here.
1948 if (JvmtiExport::should_post_field_modification()) {
1949 jvalue field_value;
1950 field_value.l = value;
1951 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1952 }
1953 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1954 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1955 } else {
1956 assert(k->is_instance_klass(), "Only instances can have flat fields");
1957 InstanceKlass* ik = InstanceKlass::cast(k);
1958 fieldDescriptor fd;
1959 ik->find_field_from_offset(offset, false, &fd);
1960 InstanceKlass* holder = fd.field_holder();
1961 InlineKlass* vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
1962 oop v = JNIHandles::resolve_non_null(value);
1963 vklass->write_flat_field(o, offset, v, CHECK);
1964 }
1965 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1966 JNI_END
1967
1968
1969 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1970 , EntryProbe, ReturnProbe) \
1971 \
1972 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1973 \
1974 EntryProbe; \
1975 \
1976 oop o = JNIHandles::resolve_non_null(obj); \
1977 Klass* k = o->klass(); \
1978 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1979 /* Keep JVMTI addition small and only check enabled flag here. */ \
1980 if (JvmtiExport::should_post_field_modification()) { \
1981 jvalue field_value; \
1982 field_value.unionType = value; \
1983 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
1984 } \
2361 Klass* ak = ek->array_klass(CHECK_NULL);
2362 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2363 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2364 oop initial_value = JNIHandles::resolve(initialElement);
2365 if (initial_value != nullptr) { // array already initialized with null
2366 for (int index = 0; index < length; index++) {
2367 result->obj_at_put(index, initial_value);
2368 }
2369 }
2370 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2371 return ret;
2372 JNI_END
2373
2374 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2375 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2376
2377 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2378 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2379 jobject ret = nullptr;
2380 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2381 oop res = nullptr;
2382 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2383 if (arr->is_within_bounds(index)) {
2384 if (arr->is_flatArray()) {
2385 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2386 flatArrayHandle vah(thread, a);
2387 res = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK_NULL);
2388 assert(res != nullptr, "Must be set in one of two paths above");
2389 } else {
2390 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2391 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2392 res = a->obj_at(index);
2393 }
2394 } else {
2395 ResourceMark rm(THREAD);
2396 stringStream ss;
2397 ss.print("Index %d out of bounds for length %d", index,arr->length());
2398 THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2399 }
2400 ret = JNIHandles::make_local(THREAD, res);
2401 return ret;
2402 JNI_END
2403
2404 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2405 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2406
2407 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2408 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2409 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2410
2411 bool oob = false;
2412 int length = -1;
2413 oop res = nullptr;
2414 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2415 if (arr->is_within_bounds(index)) {
2416 if (arr->is_flatArray()) {
2417 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2418 oop v = JNIHandles::resolve(value);
2419 FlatArrayKlass* vaklass = FlatArrayKlass::cast(a->klass());
2420 InlineKlass* element_vklass = vaklass->element_klass();
2421 if (v != nullptr && v->is_a(element_vklass)) {
2422 a->value_copy_to_index(v, index);
2423 } else {
2424 ResourceMark rm(THREAD);
2425 stringStream ss;
2426 Klass *kl = FlatArrayKlass::cast(a->klass());
2427 ss.print("type mismatch: can not store %s to %s[%d]",
2428 v->klass()->external_name(),
2429 kl->external_name(),
2430 index);
2431 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2432 ss.print("[]");
2433 }
2434 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2435 }
2436 } else {
2437 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2438 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2439 oop v = JNIHandles::resolve(value);
2440 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2441 a->obj_at_put(index, v);
2442 } else {
2443 ResourceMark rm(THREAD);
2444 stringStream ss;
2445 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2446 ss.print("type mismatch: can not store %s to %s[%d]",
2447 v->klass()->external_name(),
2448 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2449 index);
2450 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2451 ss.print("[]");
2452 }
2453 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2454 }
2455 }
2456 } else {
2457 ResourceMark rm(THREAD);
2458 stringStream ss;
2459 ss.print("Index %d out of bounds for length %d", index, arr->length());
2460 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2461 }
2462 JNI_END
2463
2464
2465
2466 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2467 ,EntryProbe,ReturnProbe) \
2468 \
2469 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2470 , ReturnProbe); \
2471 \
2472 JNI_ENTRY(Return, \
2473 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2474 EntryProbe; \
2475 Return ret = nullptr;\
2476 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2477 \
2478 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2479 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2480 return ret;\
2481 JNI_END
|