36 #include "classfile/modules.hpp"
37 #include "classfile/symbolTable.hpp"
38 #include "classfile/systemDictionary.hpp"
39 #include "classfile/vmClasses.hpp"
40 #include "classfile/vmSymbols.hpp"
41 #include "compiler/compiler_globals.hpp"
42 #include "gc/shared/collectedHeap.hpp"
43 #include "gc/shared/stringdedup/stringDedup.hpp"
44 #include "interpreter/linkResolver.hpp"
45 #include "jni.h"
46 #include "jvm.h"
47 #include "logging/log.hpp"
48 #include "memory/allocation.hpp"
49 #include "memory/allocation.inline.hpp"
50 #include "memory/oopFactory.hpp"
51 #include "memory/resourceArea.hpp"
52 #include "memory/universe.hpp"
53 #include "nmt/memTracker.hpp"
54 #include "oops/access.inline.hpp"
55 #include "oops/arrayOop.hpp"
56 #include "oops/instanceKlass.inline.hpp"
57 #include "oops/instanceOop.hpp"
58 #include "oops/klass.inline.hpp"
59 #include "oops/markWord.hpp"
60 #include "oops/method.hpp"
61 #include "oops/objArrayKlass.hpp"
62 #include "oops/objArrayOop.inline.hpp"
63 #include "oops/oop.inline.hpp"
64 #include "oops/symbol.hpp"
65 #include "oops/typeArrayKlass.hpp"
66 #include "oops/typeArrayOop.inline.hpp"
67 #include "prims/jniCheck.hpp"
68 #include "prims/jniExport.hpp"
69 #include "prims/jniFastGetField.hpp"
70 #include "prims/jvm_misc.hpp"
71 #include "prims/jvmtiExport.hpp"
72 #include "prims/jvmtiThreadState.hpp"
73 #include "runtime/arguments.hpp"
74 #include "runtime/atomic.hpp"
75 #include "runtime/fieldDescriptor.inline.hpp"
403 int modifiers = java_lang_reflect_Field::modifiers(reflected);
404
405 // Make sure class is initialized before handing id's out to fields
406 k1->initialize(CHECK_NULL);
407
408 // First check if this is a static field
409 if (modifiers & JVM_ACC_STATIC) {
410 int offset = InstanceKlass::cast(k1)->field_offset( slot );
411 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
412 assert(id != nullptr, "corrupt Field object");
413 debug_only(id->set_is_static_field_id();)
414 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
415 ret = jfieldIDWorkaround::to_static_jfieldID(id);
416 return ret;
417 }
418
419 // The slot is the index of the field description in the field-array
420 // The jfieldID is the offset of the field within the object
421 // It may also have hash bits for k, if VerifyJNIFields is turned on.
422 int offset = InstanceKlass::cast(k1)->field_offset( slot );
423 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
424 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
425 return ret;
426 JNI_END
427
428
429 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
430 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
431
432 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
433 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
434
435 jobject ret = nullptr;
436 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
437
438 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
439 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
440 oop reflection_method;
441 if (m->is_object_initializer()) {
442 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
443 } else {
444 // Note: Static initializers can theoretically be here, if JNI users manage
445 // to get their jmethodID. Record them as plain methods.
446 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
447 }
448 ret = JNIHandles::make_local(THREAD, reflection_method);
449 return ret;
450 JNI_END
451
452 DT_RETURN_MARK_DECL(GetSuperclass, jclass
453 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
454
455 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
456 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
457
458 jclass obj = nullptr;
459 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
460
461 oop mirror = JNIHandles::resolve_non_null(sub);
780 }
781
782 friend class SignatureIterator; // so do_parameters_on can call do_type
783 void do_type(BasicType type) {
784 switch (type) {
785 // these are coerced to int when using va_arg
786 case T_BYTE:
787 case T_CHAR:
788 case T_SHORT:
789 case T_INT: push_int(va_arg(_ap, jint)); break;
790 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
791
792 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
793
794 case T_LONG: push_long(va_arg(_ap, jlong)); break;
795 // float is coerced to double w/ va_arg
796 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
797 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
798
799 case T_ARRAY:
800 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
801 default: ShouldNotReachHere();
802 }
803 }
804
805 public:
806 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
807 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
808 set_ap(rap);
809 }
810
811 ~JNI_ArgumentPusherVaArg() {
812 va_end(_ap);
813 }
814
815 virtual void push_arguments_on(JavaCallArguments* arguments) {
816 _arguments = arguments;
817 do_parameters_on(this);
818 }
819 };
820
821
822 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
823 protected:
824 const jvalue *_ap;
825
826 inline void set_ap(const jvalue *rap) { _ap = rap; }
827
828 friend class SignatureIterator; // so do_parameters_on can call do_type
829 void do_type(BasicType type) {
830 switch (type) {
831 case T_CHAR: push_int((_ap++)->c); break;
832 case T_SHORT: push_int((_ap++)->s); break;
833 case T_BYTE: push_int((_ap++)->b); break;
834 case T_INT: push_int((_ap++)->i); break;
835 case T_BOOLEAN: push_boolean((_ap++)->z); break;
836 case T_LONG: push_long((_ap++)->j); break;
837 case T_FLOAT: push_float((_ap++)->f); break;
838 case T_DOUBLE: push_double((_ap++)->d); break;
839 case T_ARRAY:
840 case T_OBJECT: push_object((_ap++)->l); break;
841 default: ShouldNotReachHere();
842 }
843 }
844
845 public:
846 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
847 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
848 set_ap(rap);
849 }
850
851 virtual void push_arguments_on(JavaCallArguments* arguments) {
852 _arguments = arguments;
853 do_parameters_on(this);
854 }
855 };
856
857
858 enum JNICallType {
859 JNI_STATIC,
860 JNI_VIRTUAL,
947 result->set_type(args->return_type());
948
949 // Invoke the method. Result is returned as oop.
950 JavaCalls::call(result, method, &java_args, CHECK);
951
952 // Convert result
953 if (is_reference_type(result->get_type())) {
954 result->set_jobject(JNIHandles::make_local(THREAD, result->get_oop()));
955 }
956 }
957
958 DT_RETURN_MARK_DECL(AllocObject, jobject
959 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
960
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_NULL(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_NULL(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(); \
1812 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1813 /* Keep JVMTI addition small and only check enabled flag here. */ \
1814 if (JvmtiExport::should_post_field_access()) { \
1815 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); \
1816 } \
1817 ret = o->Fieldname##_field(offset); \
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 // TODO: make this a template
1888
1889 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1890 , EntryProbe, ReturnProbe) \
1891 \
1892 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1893 \
1894 EntryProbe; \
1895 \
1896 oop o = JNIHandles::resolve_non_null(obj); \
1897 Klass* k = o->klass(); \
1898 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1899 /* Keep JVMTI addition small and only check enabled flag here. */ \
1900 if (JvmtiExport::should_post_field_modification()) { \
1901 jvalue field_value; \
1902 field_value.unionType = value; \
1903 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
2288 Klass* ak = ek->array_klass(CHECK_NULL);
2289 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2290 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2291 oop initial_value = JNIHandles::resolve(initialElement);
2292 if (initial_value != nullptr) { // array already initialized with null
2293 for (int index = 0; index < length; index++) {
2294 result->obj_at_put(index, initial_value);
2295 }
2296 }
2297 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2298 return ret;
2299 JNI_END
2300
2301 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2302 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2303
2304 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2305 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2306 jobject ret = nullptr;
2307 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2308 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2309 if (a->is_within_bounds(index)) {
2310 ret = JNIHandles::make_local(THREAD, a->obj_at(index));
2311 return ret;
2312 } else {
2313 ResourceMark rm(THREAD);
2314 stringStream ss;
2315 ss.print("Index %d out of bounds for length %d", index, a->length());
2316 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2317 }
2318 JNI_END
2319
2320 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2321 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2322
2323 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2324 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2325 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2326
2327 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2328 oop v = JNIHandles::resolve(value);
2329 if (a->is_within_bounds(index)) {
2330 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2331 a->obj_at_put(index, v);
2332 } else {
2333 ResourceMark rm(THREAD);
2334 stringStream ss;
2335 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2336 ss.print("type mismatch: can not store %s to %s[%d]",
2337 v->klass()->external_name(),
2338 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2339 index);
2340 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2341 ss.print("[]");
2342 }
2343 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2344 }
2345 } else {
2346 ResourceMark rm(THREAD);
2347 stringStream ss;
2348 ss.print("Index %d out of bounds for length %d", index, a->length());
2349 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2350 }
2351 JNI_END
2352
2353
2354
2355 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2356 ,EntryProbe,ReturnProbe) \
2357 \
2358 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2359 , ReturnProbe); \
2360 \
2361 JNI_ENTRY(Return, \
2362 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2363 EntryProbe; \
2364 Return ret = nullptr;\
2365 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2366 \
2367 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2368 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2369 return ret;\
2370 JNI_END
2706 JNI_END
2707
2708 //
2709 // Monitor functions
2710 //
2711
2712 DT_RETURN_MARK_DECL(MonitorEnter, jint
2713 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2714
2715 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2716 HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2717 jint ret = JNI_ERR;
2718 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2719
2720 // If the object is null, we can't do anything with it
2721 if (jobj == nullptr) {
2722 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2723 }
2724
2725 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2726 ObjectSynchronizer::jni_enter(obj, thread);
2727 return JNI_OK;
2728 JNI_END
2729
2730 DT_RETURN_MARK_DECL(MonitorExit, jint
2731 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2732
2733 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2734 HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2735 jint ret = JNI_ERR;
2736 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2737
2738 // Don't do anything with a null object
2739 if (jobj == nullptr) {
2740 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2741 }
2742
2743 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2744 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2745 return JNI_OK;
2746 JNI_END
|
36 #include "classfile/modules.hpp"
37 #include "classfile/symbolTable.hpp"
38 #include "classfile/systemDictionary.hpp"
39 #include "classfile/vmClasses.hpp"
40 #include "classfile/vmSymbols.hpp"
41 #include "compiler/compiler_globals.hpp"
42 #include "gc/shared/collectedHeap.hpp"
43 #include "gc/shared/stringdedup/stringDedup.hpp"
44 #include "interpreter/linkResolver.hpp"
45 #include "jni.h"
46 #include "jvm.h"
47 #include "logging/log.hpp"
48 #include "memory/allocation.hpp"
49 #include "memory/allocation.inline.hpp"
50 #include "memory/oopFactory.hpp"
51 #include "memory/resourceArea.hpp"
52 #include "memory/universe.hpp"
53 #include "nmt/memTracker.hpp"
54 #include "oops/access.inline.hpp"
55 #include "oops/arrayOop.hpp"
56 #include "oops/flatArrayOop.inline.hpp"
57 #include "oops/inlineKlass.inline.hpp"
58 #include "oops/instanceKlass.inline.hpp"
59 #include "oops/instanceOop.hpp"
60 #include "oops/klass.inline.hpp"
61 #include "oops/markWord.hpp"
62 #include "oops/method.hpp"
63 #include "oops/objArrayKlass.hpp"
64 #include "oops/objArrayOop.inline.hpp"
65 #include "oops/oop.inline.hpp"
66 #include "oops/symbol.hpp"
67 #include "oops/typeArrayKlass.hpp"
68 #include "oops/typeArrayOop.inline.hpp"
69 #include "prims/jniCheck.hpp"
70 #include "prims/jniExport.hpp"
71 #include "prims/jniFastGetField.hpp"
72 #include "prims/jvm_misc.hpp"
73 #include "prims/jvmtiExport.hpp"
74 #include "prims/jvmtiThreadState.hpp"
75 #include "runtime/arguments.hpp"
76 #include "runtime/atomic.hpp"
77 #include "runtime/fieldDescriptor.inline.hpp"
405 int modifiers = java_lang_reflect_Field::modifiers(reflected);
406
407 // Make sure class is initialized before handing id's out to fields
408 k1->initialize(CHECK_NULL);
409
410 // First check if this is a static field
411 if (modifiers & JVM_ACC_STATIC) {
412 int offset = InstanceKlass::cast(k1)->field_offset( slot );
413 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
414 assert(id != nullptr, "corrupt Field object");
415 debug_only(id->set_is_static_field_id();)
416 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
417 ret = jfieldIDWorkaround::to_static_jfieldID(id);
418 return ret;
419 }
420
421 // The slot is the index of the field description in the field-array
422 // The jfieldID is the offset of the field within the object
423 // It may also have hash bits for k, if VerifyJNIFields is turned on.
424 int offset = InstanceKlass::cast(k1)->field_offset( slot );
425 bool is_flat = InstanceKlass::cast(k1)->field_is_flat(slot);
426 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
427 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_flat);
428 return ret;
429 JNI_END
430
431
432 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
433 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
434
435 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
436 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
437
438 jobject ret = nullptr;
439 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
440
441 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
442 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
443 oop reflection_method;
444 if (m->is_object_constructor()) {
445 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
446 } else {
447 // Note: Static initializers can theoretically be here, if JNI users manage
448 // to get their jmethodID. Record them as plain methods.
449 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
450 }
451 ret = JNIHandles::make_local(THREAD, reflection_method);
452 return ret;
453 JNI_END
454
455 DT_RETURN_MARK_DECL(GetSuperclass, jclass
456 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
457
458 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
459 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
460
461 jclass obj = nullptr;
462 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
463
464 oop mirror = JNIHandles::resolve_non_null(sub);
783 }
784
785 friend class SignatureIterator; // so do_parameters_on can call do_type
786 void do_type(BasicType type) {
787 switch (type) {
788 // these are coerced to int when using va_arg
789 case T_BYTE:
790 case T_CHAR:
791 case T_SHORT:
792 case T_INT: push_int(va_arg(_ap, jint)); break;
793 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
794
795 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
796
797 case T_LONG: push_long(va_arg(_ap, jlong)); break;
798 // float is coerced to double w/ va_arg
799 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
800 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
801
802 case T_ARRAY:
803 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
804 default: ShouldNotReachHere();
805 }
806 }
807
808 public:
809 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
810 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
811 set_ap(rap);
812 }
813
814 ~JNI_ArgumentPusherVaArg() {
815 va_end(_ap);
816 }
817
818 virtual void push_arguments_on(JavaCallArguments* arguments) {
819 _arguments = arguments;
820 do_parameters_on(this);
821 }
822 };
823
824
825 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
826 protected:
827 const jvalue *_ap;
828
829 inline void set_ap(const jvalue *rap) { _ap = rap; }
830
831 friend class SignatureIterator; // so do_parameters_on can call do_type
832 void do_type(BasicType type) {
833 switch (type) {
834 case T_CHAR: push_int((_ap++)->c); break;
835 case T_SHORT: push_int((_ap++)->s); break;
836 case T_BYTE: push_int((_ap++)->b); break;
837 case T_INT: push_int((_ap++)->i); break;
838 case T_BOOLEAN: push_boolean((_ap++)->z); break;
839 case T_LONG: push_long((_ap++)->j); break;
840 case T_FLOAT: push_float((_ap++)->f); break;
841 case T_DOUBLE: push_double((_ap++)->d); break;
842 case T_ARRAY:
843 case T_OBJECT:
844 case T_FLAT_ELEMENT: push_object((_ap++)->l); break;
845 default: ShouldNotReachHere();
846 }
847 }
848
849 public:
850 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
851 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
852 set_ap(rap);
853 }
854
855 virtual void push_arguments_on(JavaCallArguments* arguments) {
856 _arguments = arguments;
857 do_parameters_on(this);
858 }
859 };
860
861
862 enum JNICallType {
863 JNI_STATIC,
864 JNI_VIRTUAL,
951 result->set_type(args->return_type());
952
953 // Invoke the method. Result is returned as oop.
954 JavaCalls::call(result, method, &java_args, CHECK);
955
956 // Convert result
957 if (is_reference_type(result->get_type())) {
958 result->set_jobject(JNIHandles::make_local(THREAD, result->get_oop()));
959 }
960 }
961
962 DT_RETURN_MARK_DECL(AllocObject, jobject
963 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
964
965 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
966 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
967
968 jobject ret = nullptr;
969 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
970
971 oop clazzoop = JNIHandles::resolve_non_null(clazz);
972 Klass* k = java_lang_Class::as_Klass(clazzoop);
973 if (k == nullptr || k->is_inline_klass()) {
974 ResourceMark rm(THREAD);
975 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
976 }
977 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
978 ret = JNIHandles::make_local(THREAD, i);
979 return ret;
980 JNI_END
981
982 DT_RETURN_MARK_DECL(NewObjectA, jobject
983 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
984
985 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
986 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
987
988 jobject obj = nullptr;
989 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
990
991 oop clazzoop = JNIHandles::resolve_non_null(clazz);
992 Klass* k = java_lang_Class::as_Klass(clazzoop);
993 if (k == nullptr) {
994 ResourceMark rm(THREAD);
995 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
996 }
997
998 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
999 obj = JNIHandles::make_local(THREAD, i);
1000 JavaValue jvalue(T_VOID);
1001 JNI_ArgumentPusherArray ap(methodID, args);
1002 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1003
1004 return obj;
1005 JNI_END
1006
1007
1008 DT_RETURN_MARK_DECL(NewObjectV, jobject
1009 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
1010
1011 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
1012 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
1013
1014 jobject obj = nullptr;
1015 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
1016
1017 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1018 Klass* k = java_lang_Class::as_Klass(clazzoop);
1019 if (k == nullptr) {
1020 ResourceMark rm(THREAD);
1021 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1022 }
1023
1024 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1025 obj = JNIHandles::make_local(THREAD, i);
1026 JavaValue jvalue(T_VOID);
1027 JNI_ArgumentPusherVaArg ap(methodID, args);
1028 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1029
1030 return obj;
1031 JNI_END
1032
1033
1034 DT_RETURN_MARK_DECL(NewObject, jobject
1035 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1036
1037 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1038 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1039
1040 jobject obj = nullptr;
1041 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1042
1043 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1044 Klass* k = java_lang_Class::as_Klass(clazzoop);
1045 if (k == nullptr) {
1046 ResourceMark rm(THREAD);
1047 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1048 }
1049
1050 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1051 obj = JNIHandles::make_local(THREAD, i);
1052 va_list args;
1053 va_start(args, methodID);
1054 JavaValue jvalue(T_VOID);
1055 JNI_ArgumentPusherVaArg ap(methodID, args);
1056 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1057 va_end(args);
1058
1059 return obj;
1060 JNI_END
1061
1062
1063 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1064 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1065
1066 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1067 jclass ret =
1068 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1069
1070 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1071 return ret;
1072 JNI_END
1073
1074 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1075 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1076
1077 jboolean ret = JNI_TRUE;
1078 if (obj != nullptr) {
1789 // table. If they're not there, the field doesn't exist.
1790 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1791 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1792 if (fieldname == nullptr || signame == nullptr) {
1793 ResourceMark rm;
1794 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1795 }
1796
1797 // Make sure class is initialized before handing id's out to fields
1798 k->initialize(CHECK_NULL);
1799
1800 fieldDescriptor fd;
1801 if (!k->is_instance_klass() ||
1802 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1803 ResourceMark rm;
1804 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1805 }
1806
1807 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1808 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1809 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flat());
1810 return ret;
1811 JNI_END
1812
1813
1814 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1815 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1816 oop o = JNIHandles::resolve_non_null(obj);
1817 Klass* k = o->klass();
1818 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1819 oop res = nullptr;
1820 // Keep JVMTI addition small and only check enabled flag here.
1821 // jni_GetField_probe() assumes that is okay to create handles.
1822 if (JvmtiExport::should_post_field_access()) {
1823 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1824 }
1825 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1826 res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1827 } else {
1828 assert(k->is_instance_klass(), "Only instance can have flat fields");
1829 InstanceKlass* ik = InstanceKlass::cast(k);
1830 fieldDescriptor fd;
1831 bool found = ik->find_field_from_offset(offset, false, &fd); // performance bottleneck
1832 assert(found, "Field not found");
1833 InstanceKlass* holder = fd.field_holder();
1834 assert(holder->field_is_flat(fd.index()), "Must be");
1835 InlineLayoutInfo* li = holder->inline_layout_info_adr(fd.index());
1836 InlineKlass* field_vklass = li->klass();
1837 res = field_vklass->read_payload_from_addr(o, ik->field_offset(fd.index()), li->kind(), CHECK_NULL);
1838 }
1839 jobject ret = JNIHandles::make_local(THREAD, res);
1840 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1841 return ret;
1842 JNI_END
1843
1844 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1845 , EntryProbe, ReturnProbe) \
1846 \
1847 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1848 , ReturnProbe); \
1849 \
1850 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1851 \
1852 EntryProbe; \
1853 Return ret = 0;\
1854 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1855 \
1856 oop o = JNIHandles::resolve_non_null(obj); \
1857 Klass* k = o->klass(); \
1858 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1859 /* Keep JVMTI addition small and only check enabled flag here. */ \
1860 if (JvmtiExport::should_post_field_access()) { \
1861 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); \
1862 } \
1863 ret = o->Fieldname##_field(offset); \
1909 return (address)jni_GetLongField;
1910 }
1911 address jni_GetFloatField_addr() {
1912 return (address)jni_GetFloatField;
1913 }
1914 address jni_GetDoubleField_addr() {
1915 return (address)jni_GetDoubleField;
1916 }
1917
1918 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1919 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1920 oop o = JNIHandles::resolve_non_null(obj);
1921 Klass* k = o->klass();
1922 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1923 // Keep JVMTI addition small and only check enabled flag here.
1924 if (JvmtiExport::should_post_field_modification()) {
1925 jvalue field_value;
1926 field_value.l = value;
1927 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1928 }
1929 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1930 oop v = JNIHandles::resolve(value);
1931 if (v == nullptr) {
1932 InstanceKlass *ik = InstanceKlass::cast(k);
1933 fieldDescriptor fd;
1934 ik->find_field_from_offset(offset, false, &fd);
1935 if (fd.is_null_free_inline_type()) {
1936 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Cannot store null in a null-restricted field");
1937 }
1938 }
1939 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, v);
1940 } else {
1941 assert(k->is_instance_klass(), "Only instances can have flat fields");
1942 InstanceKlass* ik = InstanceKlass::cast(k);
1943 fieldDescriptor fd;
1944 ik->find_field_from_offset(offset, false, &fd);
1945 InstanceKlass* holder = fd.field_holder();
1946 InlineLayoutInfo* li = holder->inline_layout_info_adr(fd.index());
1947 InlineKlass* vklass = li->klass();
1948 oop v = JNIHandles::resolve(value);
1949 vklass->write_value_to_addr(v, ((char*)(oopDesc*)o) + offset, li->kind(), true, CHECK);
1950 }
1951 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1952 JNI_END
1953
1954 // TODO: make this a template
1955
1956 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1957 , EntryProbe, ReturnProbe) \
1958 \
1959 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1960 \
1961 EntryProbe; \
1962 \
1963 oop o = JNIHandles::resolve_non_null(obj); \
1964 Klass* k = o->klass(); \
1965 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1966 /* Keep JVMTI addition small and only check enabled flag here. */ \
1967 if (JvmtiExport::should_post_field_modification()) { \
1968 jvalue field_value; \
1969 field_value.unionType = value; \
1970 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
2355 Klass* ak = ek->array_klass(CHECK_NULL);
2356 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2357 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2358 oop initial_value = JNIHandles::resolve(initialElement);
2359 if (initial_value != nullptr) { // array already initialized with null
2360 for (int index = 0; index < length; index++) {
2361 result->obj_at_put(index, initial_value);
2362 }
2363 }
2364 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2365 return ret;
2366 JNI_END
2367
2368 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2369 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2370
2371 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2372 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2373 jobject ret = nullptr;
2374 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2375 oop res = nullptr;
2376 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2377 if (arr->is_within_bounds(index)) {
2378 if (arr->is_flatArray()) {
2379 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2380 res = a->read_value_from_flat_array(index, CHECK_NULL);
2381 assert(res != nullptr || !arr->is_null_free_array(), "Invalid value");
2382 } else {
2383 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2384 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2385 res = a->obj_at(index);
2386 }
2387 } else {
2388 ResourceMark rm(THREAD);
2389 stringStream ss;
2390 ss.print("Index %d out of bounds for length %d", index,arr->length());
2391 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2392 }
2393 ret = JNIHandles::make_local(THREAD, res);
2394 return ret;
2395 JNI_END
2396
2397 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2398 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2399
2400 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2401 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2402 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2403
2404 bool oob = false;
2405 int length = -1;
2406 oop res = nullptr;
2407 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2408 if (arr->is_within_bounds(index)) {
2409 if (arr->is_flatArray()) {
2410 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2411 oop v = JNIHandles::resolve(value);
2412 FlatArrayKlass* vaklass = FlatArrayKlass::cast(a->klass());
2413 InlineKlass* element_vklass = vaklass->element_klass();
2414 a->write_value_to_flat_array(v, index, CHECK);
2415 } else {
2416 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2417 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2418 oop v = JNIHandles::resolve(value);
2419 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2420 if (v == nullptr && ObjArrayKlass::cast(a->klass())->is_null_free_array_klass()) {
2421 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Cannot store null in a null-restricted array");
2422 }
2423 a->obj_at_put(index, v);
2424 } else {
2425 ResourceMark rm(THREAD);
2426 stringStream ss;
2427 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2428 ss.print("type mismatch: can not store %s to %s[%d]",
2429 v->klass()->external_name(),
2430 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2431 index);
2432 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2433 ss.print("[]");
2434 }
2435 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2436 }
2437 }
2438 } else {
2439 ResourceMark rm(THREAD);
2440 stringStream ss;
2441 ss.print("Index %d out of bounds for length %d", index, arr->length());
2442 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2443 }
2444 JNI_END
2445
2446
2447
2448 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2449 ,EntryProbe,ReturnProbe) \
2450 \
2451 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2452 , ReturnProbe); \
2453 \
2454 JNI_ENTRY(Return, \
2455 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2456 EntryProbe; \
2457 Return ret = nullptr;\
2458 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2459 \
2460 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2461 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2462 return ret;\
2463 JNI_END
2799 JNI_END
2800
2801 //
2802 // Monitor functions
2803 //
2804
2805 DT_RETURN_MARK_DECL(MonitorEnter, jint
2806 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2807
2808 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2809 HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2810 jint ret = JNI_ERR;
2811 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2812
2813 // If the object is null, we can't do anything with it
2814 if (jobj == nullptr) {
2815 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2816 }
2817
2818 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2819 ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
2820 return JNI_OK;
2821 JNI_END
2822
2823 DT_RETURN_MARK_DECL(MonitorExit, jint
2824 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2825
2826 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2827 HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2828 jint ret = JNI_ERR;
2829 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2830
2831 // Don't do anything with a null object
2832 if (jobj == nullptr) {
2833 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2834 }
2835
2836 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2837 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2838 return JNI_OK;
2839 JNI_END
|