34 #include "classfile/moduleEntry.hpp"
35 #include "classfile/modules.hpp"
36 #include "classfile/symbolTable.hpp"
37 #include "classfile/systemDictionary.hpp"
38 #include "classfile/vmClasses.hpp"
39 #include "classfile/vmSymbols.hpp"
40 #include "compiler/compiler_globals.hpp"
41 #include "gc/shared/collectedHeap.hpp"
42 #include "gc/shared/stringdedup/stringDedup.hpp"
43 #include "interpreter/linkResolver.hpp"
44 #include "jni.h"
45 #include "jvm.h"
46 #include "logging/log.hpp"
47 #include "memory/allocation.inline.hpp"
48 #include "memory/oopFactory.hpp"
49 #include "memory/resourceArea.hpp"
50 #include "memory/universe.hpp"
51 #include "nmt/memTracker.hpp"
52 #include "oops/access.inline.hpp"
53 #include "oops/arrayOop.hpp"
54 #include "oops/instanceKlass.inline.hpp"
55 #include "oops/instanceOop.hpp"
56 #include "oops/klass.inline.hpp"
57 #include "oops/markWord.hpp"
58 #include "oops/method.hpp"
59 #include "oops/objArrayKlass.hpp"
60 #include "oops/objArrayOop.inline.hpp"
61 #include "oops/oop.inline.hpp"
62 #include "oops/symbol.hpp"
63 #include "oops/typeArrayKlass.hpp"
64 #include "oops/typeArrayOop.inline.hpp"
65 #include "prims/jniCheck.hpp"
66 #include "prims/jniExport.hpp"
67 #include "prims/jniFastGetField.hpp"
68 #include "prims/jvm_misc.hpp"
69 #include "prims/jvmtiExport.hpp"
70 #include "prims/jvmtiThreadState.hpp"
71 #include "runtime/arguments.hpp"
72 #include "runtime/atomicAccess.hpp"
73 #include "runtime/fieldDescriptor.inline.hpp"
401 int modifiers = java_lang_reflect_Field::modifiers(reflected);
402
403 // Make sure class is initialized before handing id's out to fields
404 k1->initialize(CHECK_NULL);
405
406 // First check if this is a static field
407 if (modifiers & JVM_ACC_STATIC) {
408 int offset = InstanceKlass::cast(k1)->field_offset( slot );
409 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
410 assert(id != nullptr, "corrupt Field object");
411 DEBUG_ONLY(id->set_is_static_field_id();)
412 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
413 ret = jfieldIDWorkaround::to_static_jfieldID(id);
414 return ret;
415 }
416
417 // The slot is the index of the field description in the field-array
418 // The jfieldID is the offset of the field within the object
419 // It may also have hash bits for k, if VerifyJNIFields is turned on.
420 int offset = InstanceKlass::cast(k1)->field_offset( slot );
421 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
422 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
423 return ret;
424 JNI_END
425
426
427 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
428 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
429
430 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
431 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
432
433 jobject ret = nullptr;
434 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
435
436 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
437 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
438 oop reflection_method;
439 if (m->is_object_initializer()) {
440 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
441 } else {
442 // Note: Static initializers can theoretically be here, if JNI users manage
443 // to get their jmethodID. Record them as plain methods.
444 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
445 }
446 ret = JNIHandles::make_local(THREAD, reflection_method);
447 return ret;
448 JNI_END
449
450 DT_RETURN_MARK_DECL(GetSuperclass, jclass
451 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
452
453 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
454 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
455
456 jclass obj = nullptr;
457 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
458
459 oop mirror = JNIHandles::resolve_non_null(sub);
778 }
779
780 friend class SignatureIterator; // so do_parameters_on can call do_type
781 void do_type(BasicType type) {
782 switch (type) {
783 // these are coerced to int when using va_arg
784 case T_BYTE:
785 case T_CHAR:
786 case T_SHORT:
787 case T_INT: push_int(va_arg(_ap, jint)); break;
788 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
789
790 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
791
792 case T_LONG: push_long(va_arg(_ap, jlong)); break;
793 // float is coerced to double w/ va_arg
794 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
795 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
796
797 case T_ARRAY:
798 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
799 default: ShouldNotReachHere();
800 }
801 }
802
803 public:
804 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
805 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
806 set_ap(rap);
807 }
808
809 ~JNI_ArgumentPusherVaArg() {
810 va_end(_ap);
811 }
812
813 virtual void push_arguments_on(JavaCallArguments* arguments) {
814 _arguments = arguments;
815 do_parameters_on(this);
816 }
817 };
818
945 result->set_type(args->return_type());
946
947 // Invoke the method. Result is returned as oop.
948 JavaCalls::call(result, method, &java_args, CHECK);
949
950 // Convert result
951 if (is_reference_type(result->get_type())) {
952 result->set_jobject(JNIHandles::make_local(THREAD, result->get_oop()));
953 }
954 }
955
956 DT_RETURN_MARK_DECL(AllocObject, jobject
957 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
958
959 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
960 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
961
962 jobject ret = nullptr;
963 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
964
965 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
966 ret = JNIHandles::make_local(THREAD, i);
967 return ret;
968 JNI_END
969
970 DT_RETURN_MARK_DECL(NewObjectA, jobject
971 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
972
973 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
974 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
975
976 jobject obj = nullptr;
977 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
978
979 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
980 obj = JNIHandles::make_local(THREAD, i);
981 JavaValue jvalue(T_VOID);
982 JNI_ArgumentPusherArray ap(methodID, args);
983 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
984 return obj;
985 JNI_END
986
987
988 DT_RETURN_MARK_DECL(NewObjectV, jobject
989 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
990
991 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
992 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
993
994 jobject obj = nullptr;
995 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
996
997 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
998 obj = JNIHandles::make_local(THREAD, i);
999 JavaValue jvalue(T_VOID);
1000 JNI_ArgumentPusherVaArg ap(methodID, args);
1001 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1002 return obj;
1003 JNI_END
1004
1005
1006 DT_RETURN_MARK_DECL(NewObject, jobject
1007 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1008
1009 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1010 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1011
1012 jobject obj = nullptr;
1013 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1014
1015 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
1016 obj = JNIHandles::make_local(THREAD, i);
1017 va_list args;
1018 va_start(args, methodID);
1019 JavaValue jvalue(T_VOID);
1020 JNI_ArgumentPusherVaArg ap(methodID, args);
1021 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1022 va_end(args);
1023 return obj;
1024 JNI_END
1025
1026
1027 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1028 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1029
1030 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1031 jclass ret =
1032 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1033
1034 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1035 return ret;
1036 JNI_END
1037
1038 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1039 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1040
1041 jboolean ret = JNI_TRUE;
1042 if (obj != nullptr) {
1753 // table. If they're not there, the field doesn't exist.
1754 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1755 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1756 if (fieldname == nullptr || signame == nullptr) {
1757 ResourceMark rm;
1758 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1759 }
1760
1761 // Make sure class is initialized before handing id's out to fields
1762 k->initialize(CHECK_NULL);
1763
1764 fieldDescriptor fd;
1765 if (!k->is_instance_klass() ||
1766 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1767 ResourceMark rm;
1768 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1769 }
1770
1771 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1772 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1773 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
1774 return ret;
1775 JNI_END
1776
1777
1778 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1779 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1780 oop o = JNIHandles::resolve_non_null(obj);
1781 Klass* k = o->klass();
1782 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1783 // Keep JVMTI addition small and only check enabled flag here.
1784 // jni_GetField_probe() assumes that is okay to create handles.
1785 if (JvmtiExport::should_post_field_access()) {
1786 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1787 }
1788 oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1789 jobject ret = JNIHandles::make_local(THREAD, loaded_obj);
1790 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1791 return ret;
1792 JNI_END
1793
1794
1795
1796 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1797 , EntryProbe, ReturnProbe) \
1798 \
1799 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1800 , ReturnProbe); \
1801 \
1802 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1803 \
1804 EntryProbe; \
1805 Return ret = 0;\
1806 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1807 \
1808 oop o = JNIHandles::resolve_non_null(obj); \
1809 Klass* k = o->klass(); \
1810 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1811 /* Keep JVMTI addition small and only check enabled flag here. */ \
1812 if (JvmtiExport::should_post_field_access()) { \
1813 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); \
1814 } \
1815 ret = o->Fieldname##_field(offset); \
1887 assert(found, "bad field offset");
1888 assert(!fd.is_static(), "static/instance mismatch");
1889 if (fd.is_final()) {
1890 ResourceMark rm(current);
1891 log_debug(jni)("%s mutated final instance field %s.%s", func_name, ik->external_name(), fd.name()->as_C_string());
1892 }
1893 }
1894 }
1895
1896 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1897 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1898 oop o = JNIHandles::resolve_non_null(obj);
1899 Klass* k = o->klass();
1900 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1901 // Keep JVMTI addition small and only check enabled flag here.
1902 if (JvmtiExport::should_post_field_modification()) {
1903 jvalue field_value;
1904 field_value.l = value;
1905 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1906 }
1907 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1908 log_debug_if_final_instance_field(thread, "SetObjectField", InstanceKlass::cast(k), offset);
1909 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1910 JNI_END
1911
1912 // TODO: make this a template
1913
1914 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1915 , EntryProbe, ReturnProbe) \
1916 \
1917 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1918 \
1919 EntryProbe; \
1920 \
1921 oop o = JNIHandles::resolve_non_null(obj); \
1922 Klass* k = o->klass(); \
1923 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1924 /* Keep JVMTI addition small and only check enabled flag here. */ \
1925 if (JvmtiExport::should_post_field_modification()) { \
1926 jvalue field_value; \
1927 field_value.unionType = value; \
2320
2321 oop initial_value = JNIHandles::resolve(initialElement);
2322 if (initial_value != nullptr) { // array already initialized with null
2323 for (int index = 0; index < length; index++) {
2324 result->obj_at_put(index, initial_value);
2325 }
2326 }
2327 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2328 return ret;
2329 JNI_END
2330
2331 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2332 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2333
2334 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2335 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2336 jobject ret = nullptr;
2337 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2338 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2339 if (a->is_within_bounds(index)) {
2340 ret = JNIHandles::make_local(THREAD, a->obj_at(index));
2341 return ret;
2342 } else {
2343 ResourceMark rm(THREAD);
2344 stringStream ss;
2345 ss.print("Index %d out of bounds for length %d", index, a->length());
2346 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2347 }
2348 JNI_END
2349
2350 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2351 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2352
2353 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2354 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2355 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2356
2357 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2358 oop v = JNIHandles::resolve(value);
2359 if (a->is_within_bounds(index)) {
2360 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2361 a->obj_at_put(index, v);
2362 } else {
2363 ResourceMark rm(THREAD);
2364 stringStream ss;
2365 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2366 ss.print("type mismatch: can not store %s to %s[%d]",
2367 v->klass()->external_name(),
2368 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2369 index);
2370 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2371 ss.print("[]");
2372 }
2373 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2374 }
2375 } else {
2376 ResourceMark rm(THREAD);
2377 stringStream ss;
2378 ss.print("Index %d out of bounds for length %d", index, a->length());
2379 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2380 }
2381 JNI_END
2382
2383
2384
2385 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2386 ,EntryProbe,ReturnProbe) \
2387 \
2388 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2389 , ReturnProbe); \
2390 \
2391 JNI_ENTRY(Return, \
2392 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2393 EntryProbe; \
2394 Return ret = nullptr;\
2395 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2396 \
2397 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2398 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2399 return ret;\
2400 JNI_END
2736 JNI_END
2737
2738 //
2739 // Monitor functions
2740 //
2741
2742 DT_RETURN_MARK_DECL(MonitorEnter, jint
2743 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2744
2745 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2746 HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2747 jint ret = JNI_ERR;
2748 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2749
2750 // If the object is null, we can't do anything with it
2751 if (jobj == nullptr) {
2752 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2753 }
2754
2755 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2756 ObjectSynchronizer::jni_enter(obj, thread);
2757 return JNI_OK;
2758 JNI_END
2759
2760 DT_RETURN_MARK_DECL(MonitorExit, jint
2761 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2762
2763 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2764 HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2765 jint ret = JNI_ERR;
2766 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2767
2768 // Don't do anything with a null object
2769 if (jobj == nullptr) {
2770 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2771 }
2772
2773 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2774 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2775 return JNI_OK;
2776 JNI_END
|
34 #include "classfile/moduleEntry.hpp"
35 #include "classfile/modules.hpp"
36 #include "classfile/symbolTable.hpp"
37 #include "classfile/systemDictionary.hpp"
38 #include "classfile/vmClasses.hpp"
39 #include "classfile/vmSymbols.hpp"
40 #include "compiler/compiler_globals.hpp"
41 #include "gc/shared/collectedHeap.hpp"
42 #include "gc/shared/stringdedup/stringDedup.hpp"
43 #include "interpreter/linkResolver.hpp"
44 #include "jni.h"
45 #include "jvm.h"
46 #include "logging/log.hpp"
47 #include "memory/allocation.inline.hpp"
48 #include "memory/oopFactory.hpp"
49 #include "memory/resourceArea.hpp"
50 #include "memory/universe.hpp"
51 #include "nmt/memTracker.hpp"
52 #include "oops/access.inline.hpp"
53 #include "oops/arrayOop.hpp"
54 #include "oops/flatArrayOop.inline.hpp"
55 #include "oops/inlineKlass.inline.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/atomicAccess.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 bool is_flat = InstanceKlass::cast(k1)->field_is_flat(slot);
424 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
425 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_flat);
426 return ret;
427 JNI_END
428
429
430 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
431 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
432
433 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
434 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
435
436 jobject ret = nullptr;
437 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
438
439 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
440 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
441 oop reflection_method;
442 if (m->is_object_constructor()) {
443 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
444 } else {
445 // Note: Static initializers can theoretically be here, if JNI users manage
446 // to get their jmethodID. Record them as plain methods.
447 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
448 }
449 ret = JNIHandles::make_local(THREAD, reflection_method);
450 return ret;
451 JNI_END
452
453 DT_RETURN_MARK_DECL(GetSuperclass, jclass
454 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
455
456 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
457 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
458
459 jclass obj = nullptr;
460 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
461
462 oop mirror = JNIHandles::resolve_non_null(sub);
781 }
782
783 friend class SignatureIterator; // so do_parameters_on can call do_type
784 void do_type(BasicType type) {
785 switch (type) {
786 // these are coerced to int when using va_arg
787 case T_BYTE:
788 case T_CHAR:
789 case T_SHORT:
790 case T_INT: push_int(va_arg(_ap, jint)); break;
791 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
792
793 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
794
795 case T_LONG: push_long(va_arg(_ap, jlong)); break;
796 // float is coerced to double w/ va_arg
797 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
798 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
799
800 case T_ARRAY:
801 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
802 default: ShouldNotReachHere();
803 }
804 }
805
806 public:
807 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
808 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
809 set_ap(rap);
810 }
811
812 ~JNI_ArgumentPusherVaArg() {
813 va_end(_ap);
814 }
815
816 virtual void push_arguments_on(JavaCallArguments* arguments) {
817 _arguments = arguments;
818 do_parameters_on(this);
819 }
820 };
821
948 result->set_type(args->return_type());
949
950 // Invoke the method. Result is returned as oop.
951 JavaCalls::call(result, method, &java_args, CHECK);
952
953 // Convert result
954 if (is_reference_type(result->get_type())) {
955 result->set_jobject(JNIHandles::make_local(THREAD, result->get_oop()));
956 }
957 }
958
959 DT_RETURN_MARK_DECL(AllocObject, jobject
960 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
961
962 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
963 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
964
965 jobject ret = nullptr;
966 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
967
968 oop clazzoop = JNIHandles::resolve_non_null(clazz);
969 Klass* k = java_lang_Class::as_Klass(clazzoop);
970 if (k == nullptr || k->is_inline_klass()) {
971 ResourceMark rm(THREAD);
972 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
973 }
974 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
975 ret = JNIHandles::make_local(THREAD, i);
976 return ret;
977 JNI_END
978
979 DT_RETURN_MARK_DECL(NewObjectA, jobject
980 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
981
982 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
983 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
984
985 jobject obj = nullptr;
986 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
987
988 oop clazzoop = JNIHandles::resolve_non_null(clazz);
989 Klass* k = java_lang_Class::as_Klass(clazzoop);
990 if (k == nullptr) {
991 ResourceMark rm(THREAD);
992 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
993 }
994
995 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
996 obj = JNIHandles::make_local(THREAD, i);
997 JavaValue jvalue(T_VOID);
998 JNI_ArgumentPusherArray ap(methodID, args);
999 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1000
1001 return obj;
1002 JNI_END
1003
1004
1005 DT_RETURN_MARK_DECL(NewObjectV, jobject
1006 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
1007
1008 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
1009 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
1010
1011 jobject obj = nullptr;
1012 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
1013
1014 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1015 Klass* k = java_lang_Class::as_Klass(clazzoop);
1016 if (k == nullptr) {
1017 ResourceMark rm(THREAD);
1018 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1019 }
1020
1021 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1022 obj = JNIHandles::make_local(THREAD, i);
1023 JavaValue jvalue(T_VOID);
1024 JNI_ArgumentPusherVaArg ap(methodID, args);
1025 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1026
1027 return obj;
1028 JNI_END
1029
1030
1031 DT_RETURN_MARK_DECL(NewObject, jobject
1032 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1033
1034 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1035 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1036
1037 jobject obj = nullptr;
1038 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1039
1040 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1041 Klass* k = java_lang_Class::as_Klass(clazzoop);
1042 if (k == nullptr) {
1043 ResourceMark rm(THREAD);
1044 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1045 }
1046
1047 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1048 obj = JNIHandles::make_local(THREAD, i);
1049 va_list args;
1050 va_start(args, methodID);
1051 JavaValue jvalue(T_VOID);
1052 JNI_ArgumentPusherVaArg ap(methodID, args);
1053 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1054 va_end(args);
1055
1056 return obj;
1057 JNI_END
1058
1059
1060 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1061 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1062
1063 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1064 jclass ret =
1065 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1066
1067 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1068 return ret;
1069 JNI_END
1070
1071 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1072 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1073
1074 jboolean ret = JNI_TRUE;
1075 if (obj != nullptr) {
1786 // table. If they're not there, the field doesn't exist.
1787 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1788 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1789 if (fieldname == nullptr || signame == nullptr) {
1790 ResourceMark rm;
1791 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1792 }
1793
1794 // Make sure class is initialized before handing id's out to fields
1795 k->initialize(CHECK_NULL);
1796
1797 fieldDescriptor fd;
1798 if (!k->is_instance_klass() ||
1799 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1800 ResourceMark rm;
1801 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1802 }
1803
1804 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1805 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1806 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flat());
1807 return ret;
1808 JNI_END
1809
1810
1811 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1812 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1813 oop o = JNIHandles::resolve_non_null(obj);
1814 Klass* k = o->klass();
1815 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1816 oop res = nullptr;
1817 // Keep JVMTI addition small and only check enabled flag here.
1818 // jni_GetField_probe() assumes that is okay to create handles.
1819 if (JvmtiExport::should_post_field_access()) {
1820 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1821 }
1822 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1823 res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1824 } else {
1825 assert(k->is_instance_klass(), "Only instance can have flat fields");
1826 InstanceKlass* ik = InstanceKlass::cast(k);
1827 fieldDescriptor fd;
1828 bool found = ik->find_field_from_offset(offset, false, &fd); // performance bottleneck
1829 assert(found, "Field not found");
1830 InstanceKlass* holder = fd.field_holder();
1831 assert(holder->field_is_flat(fd.index()), "Must be");
1832 InlineLayoutInfo* li = holder->inline_layout_info_adr(fd.index());
1833 InlineKlass* field_vklass = li->klass();
1834 res = field_vklass->read_payload_from_addr(o, ik->field_offset(fd.index()), li->kind(), CHECK_NULL);
1835 }
1836 jobject ret = JNIHandles::make_local(THREAD, res);
1837 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1838 return ret;
1839 JNI_END
1840
1841 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1842 , EntryProbe, ReturnProbe) \
1843 \
1844 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1845 , ReturnProbe); \
1846 \
1847 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1848 \
1849 EntryProbe; \
1850 Return ret = 0;\
1851 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1852 \
1853 oop o = JNIHandles::resolve_non_null(obj); \
1854 Klass* k = o->klass(); \
1855 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1856 /* Keep JVMTI addition small and only check enabled flag here. */ \
1857 if (JvmtiExport::should_post_field_access()) { \
1858 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); \
1859 } \
1860 ret = o->Fieldname##_field(offset); \
1932 assert(found, "bad field offset");
1933 assert(!fd.is_static(), "static/instance mismatch");
1934 if (fd.is_final()) {
1935 ResourceMark rm(current);
1936 log_debug(jni)("%s mutated final instance field %s.%s", func_name, ik->external_name(), fd.name()->as_C_string());
1937 }
1938 }
1939 }
1940
1941 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1942 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1943 oop o = JNIHandles::resolve_non_null(obj);
1944 Klass* k = o->klass();
1945 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1946 // Keep JVMTI addition small and only check enabled flag here.
1947 if (JvmtiExport::should_post_field_modification()) {
1948 jvalue field_value;
1949 field_value.l = value;
1950 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1951 }
1952 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1953 oop v = JNIHandles::resolve(value);
1954 if (v == nullptr) {
1955 InstanceKlass *ik = InstanceKlass::cast(k);
1956 fieldDescriptor fd;
1957 ik->find_field_from_offset(offset, false, &fd);
1958 if (fd.is_null_free_inline_type()) {
1959 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Cannot store null in a null-restricted field");
1960 }
1961 }
1962 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, v);
1963 } else {
1964 assert(k->is_instance_klass(), "Only instances can have flat fields");
1965 InstanceKlass* ik = InstanceKlass::cast(k);
1966 fieldDescriptor fd;
1967 ik->find_field_from_offset(offset, false, &fd);
1968 InstanceKlass* holder = fd.field_holder();
1969 InlineLayoutInfo* li = holder->inline_layout_info_adr(fd.index());
1970 InlineKlass* vklass = li->klass();
1971 oop v = JNIHandles::resolve(value);
1972 vklass->write_value_to_addr(v, ((char*)(oopDesc*)o) + offset, li->kind(), true, CHECK);
1973 }
1974 log_debug_if_final_instance_field(thread, "SetObjectField", InstanceKlass::cast(k), offset);
1975 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1976 JNI_END
1977
1978 // TODO: make this a template
1979
1980 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1981 , EntryProbe, ReturnProbe) \
1982 \
1983 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1984 \
1985 EntryProbe; \
1986 \
1987 oop o = JNIHandles::resolve_non_null(obj); \
1988 Klass* k = o->klass(); \
1989 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1990 /* Keep JVMTI addition small and only check enabled flag here. */ \
1991 if (JvmtiExport::should_post_field_modification()) { \
1992 jvalue field_value; \
1993 field_value.unionType = value; \
2386
2387 oop initial_value = JNIHandles::resolve(initialElement);
2388 if (initial_value != nullptr) { // array already initialized with null
2389 for (int index = 0; index < length; index++) {
2390 result->obj_at_put(index, initial_value);
2391 }
2392 }
2393 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2394 return ret;
2395 JNI_END
2396
2397 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2398 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2399
2400 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2401 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2402 jobject ret = nullptr;
2403 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2404 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2405 if (a->is_within_bounds(index)) {
2406 oop res = a->obj_at(index, CHECK_NULL);
2407 assert(res != nullptr || !a->is_null_free_array(), "Invalid value");
2408 ret = JNIHandles::make_local(THREAD, res);
2409 return ret;
2410 } else {
2411 ResourceMark rm(THREAD);
2412 stringStream ss;
2413 ss.print("Index %d out of bounds for length %d", index, a->length());
2414 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2415 }
2416 JNI_END
2417
2418 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2419 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2420
2421 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2422 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2423 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2424
2425 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2426 oop v = JNIHandles::resolve(value);
2427 if (a->is_within_bounds(index)) {
2428 Klass* ek = a->is_flatArray() ? FlatArrayKlass::cast(a->klass())->element_klass() : RefArrayKlass::cast(a->klass())->element_klass();
2429 if (v == nullptr || v->is_a(ek)) {
2430 a->obj_at_put(index, v, CHECK);
2431 } else {
2432 ResourceMark rm(THREAD);
2433 stringStream ss;
2434 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2435 ss.print("type mismatch: can not store %s to %s[%d]",
2436 v->klass()->external_name(),
2437 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2438 index);
2439 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2440 ss.print("[]");
2441 }
2442 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2443 }
2444 } else {
2445 ResourceMark rm(THREAD);
2446 stringStream ss;
2447 ss.print("Index %d out of bounds for length %d", index, a->length());
2448 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2449 }
2450 JNI_END
2451
2452
2453
2454 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2455 ,EntryProbe,ReturnProbe) \
2456 \
2457 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2458 , ReturnProbe); \
2459 \
2460 JNI_ENTRY(Return, \
2461 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2462 EntryProbe; \
2463 Return ret = nullptr;\
2464 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2465 \
2466 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2467 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2468 return ret;\
2469 JNI_END
2805 JNI_END
2806
2807 //
2808 // Monitor functions
2809 //
2810
2811 DT_RETURN_MARK_DECL(MonitorEnter, jint
2812 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2813
2814 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2815 HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2816 jint ret = JNI_ERR;
2817 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2818
2819 // If the object is null, we can't do anything with it
2820 if (jobj == nullptr) {
2821 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2822 }
2823
2824 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2825 ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
2826 return JNI_OK;
2827 JNI_END
2828
2829 DT_RETURN_MARK_DECL(MonitorExit, jint
2830 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2831
2832 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2833 HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2834 jint ret = JNI_ERR;
2835 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2836
2837 // Don't do anything with a null object
2838 if (jobj == nullptr) {
2839 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2840 }
2841
2842 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2843 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2844 return JNI_OK;
2845 JNI_END
|