33 #include "classfile/javaThreadStatus.hpp"
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"
74 #include "runtime/handles.inline.hpp"
75 #include "runtime/interfaceSupport.inline.hpp"
76 #include "runtime/java.hpp"
77 #include "runtime/javaCalls.hpp"
78 #include "runtime/javaThread.inline.hpp"
79 #include "runtime/jfieldIDWorkaround.hpp"
80 #include "runtime/jniHandles.inline.hpp"
81 #include "runtime/reflection.hpp"
82 #include "runtime/safepointVerifiers.hpp"
83 #include "runtime/sharedRuntime.hpp"
84 #include "runtime/signature.hpp"
398 int modifiers = java_lang_reflect_Field::modifiers(reflected);
399
400 // Make sure class is initialized before handing id's out to fields
401 k1->initialize(CHECK_NULL);
402
403 // First check if this is a static field
404 if (modifiers & JVM_ACC_STATIC) {
405 int offset = InstanceKlass::cast(k1)->field_offset( slot );
406 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
407 assert(id != nullptr, "corrupt Field object");
408 DEBUG_ONLY(id->set_is_static_field_id();)
409 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
410 ret = jfieldIDWorkaround::to_static_jfieldID(id);
411 return ret;
412 }
413
414 // The slot is the index of the field description in the field-array
415 // The jfieldID is the offset of the field within the object
416 // It may also have hash bits for k, if VerifyJNIFields is turned on.
417 int offset = InstanceKlass::cast(k1)->field_offset( slot );
418 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
419 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
420 return ret;
421 JNI_END
422
423
424 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
425 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
426
427 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
428 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
429
430 jobject ret = nullptr;
431 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
432
433 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
434 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
435 oop reflection_method;
436 if (m->is_object_initializer()) {
437 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
438 } else {
439 // Note: Static initializers can theoretically be here, if JNI users manage
440 // to get their jmethodID. Record them as plain methods.
441 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
442 }
443 ret = JNIHandles::make_local(THREAD, reflection_method);
444 return ret;
445 JNI_END
446
447 DT_RETURN_MARK_DECL(GetSuperclass, jclass
448 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
449
450 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
451 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
452
453 jclass obj = nullptr;
454 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
455
456 oop mirror = JNIHandles::resolve_non_null(sub);
1749 // table. If they're not there, the field doesn't exist.
1750 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1751 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1752 if (fieldname == nullptr || signame == nullptr) {
1753 ResourceMark rm;
1754 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1755 }
1756
1757 // Make sure class is initialized before handing id's out to fields
1758 k->initialize(CHECK_NULL);
1759
1760 fieldDescriptor fd;
1761 if (!k->is_instance_klass() ||
1762 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1763 ResourceMark rm;
1764 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1765 }
1766
1767 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1768 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1769 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
1770 return ret;
1771 JNI_END
1772
1773
1774 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1775 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1776 oop o = JNIHandles::resolve_non_null(obj);
1777 Klass* k = o->klass();
1778 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1779 // Keep JVMTI addition small and only check enabled flag here.
1780 // jni_GetField_probe() assumes that is okay to create handles.
1781 if (JvmtiExport::should_post_field_access()) {
1782 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1783 }
1784 oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1785 jobject ret = JNIHandles::make_local(THREAD, loaded_obj);
1786 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1787 return ret;
1788 JNI_END
1789
1790
1791
1792 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1793 , EntryProbe, ReturnProbe) \
1794 \
1795 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1796 , ReturnProbe); \
1797 \
1798 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1799 \
1800 EntryProbe; \
1801 Return ret = 0;\
1802 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1803 \
1804 oop o = JNIHandles::resolve_non_null(obj); \
1805 Klass* k = o->klass(); \
1883 assert(found, "bad field offset");
1884 assert(!fd.is_static(), "static/instance mismatch");
1885 if (fd.is_final()) {
1886 ResourceMark rm(current);
1887 log_debug(jni)("%s mutated final instance field %s.%s", func_name, ik->external_name(), fd.name()->as_C_string());
1888 }
1889 }
1890 }
1891
1892 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1893 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1894 oop o = JNIHandles::resolve_non_null(obj);
1895 Klass* k = o->klass();
1896 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1897 // Keep JVMTI addition small and only check enabled flag here.
1898 if (JvmtiExport::should_post_field_modification()) {
1899 jvalue field_value;
1900 field_value.l = value;
1901 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1902 }
1903 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1904 log_debug_if_final_instance_field(thread, "SetObjectField", InstanceKlass::cast(k), offset);
1905 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1906 JNI_END
1907
1908 // TODO: make this a template
1909
1910 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1911 , EntryProbe, ReturnProbe) \
1912 \
1913 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1914 \
1915 EntryProbe; \
1916 \
1917 oop o = JNIHandles::resolve_non_null(obj); \
1918 Klass* k = o->klass(); \
1919 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1920 /* Keep JVMTI addition small and only check enabled flag here. */ \
1921 if (JvmtiExport::should_post_field_modification()) { \
1922 jvalue field_value; \
1923 field_value.unionType = value; \
2314 ek->initialize(CHECK_NULL);
2315 objArrayOop result = oopFactory::new_objArray(ek, length, CHECK_NULL);
2316
2317 oop initial_value = JNIHandles::resolve(initialElement);
2318 if (initial_value != nullptr) { // array already initialized with null
2319 for (int index = 0; index < length; index++) {
2320 result->obj_at_put(index, initial_value);
2321 }
2322 }
2323 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2324 return ret;
2325 JNI_END
2326
2327 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2328 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2329
2330 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2331 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2332 jobject ret = nullptr;
2333 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2334 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2335 if (a->is_within_bounds(index)) {
2336 ret = JNIHandles::make_local(THREAD, a->obj_at(index));
2337 return ret;
2338 } else {
2339 ResourceMark rm(THREAD);
2340 stringStream ss;
2341 ss.print("Index %d out of bounds for length %d", index, a->length());
2342 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2343 }
2344 JNI_END
2345
2346 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2347 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2348
2349 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2350 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2351 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2352
2353 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2354 oop v = JNIHandles::resolve(value);
2355 if (a->is_within_bounds(index)) {
2356 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2357 a->obj_at_put(index, v);
2358 } else {
2359 ResourceMark rm(THREAD);
2360 stringStream ss;
2361 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2362 ss.print("type mismatch: can not store %s to %s[%d]",
2363 v->klass()->external_name(),
2364 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2365 index);
2366 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2367 ss.print("[]");
2368 }
2369 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2370 }
2371 } else {
2372 ResourceMark rm(THREAD);
2373 stringStream ss;
2374 ss.print("Index %d out of bounds for length %d", index, a->length());
2375 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2376 }
2377 JNI_END
2732 JNI_END
2733
2734 //
2735 // Monitor functions
2736 //
2737
2738 DT_RETURN_MARK_DECL(MonitorEnter, jint
2739 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2740
2741 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2742 HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2743 jint ret = JNI_ERR;
2744 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2745
2746 // If the object is null, we can't do anything with it
2747 if (jobj == nullptr) {
2748 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2749 }
2750
2751 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2752 ObjectSynchronizer::jni_enter(obj, thread);
2753 return JNI_OK;
2754 JNI_END
2755
2756 DT_RETURN_MARK_DECL(MonitorExit, jint
2757 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2758
2759 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2760 HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2761 jint ret = JNI_ERR;
2762 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2763
2764 // Don't do anything with a null object
2765 if (jobj == nullptr) {
2766 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2767 }
2768
2769 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2770 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2771 return JNI_OK;
2772 JNI_END
2908 if (is_latin1) {
2909 // For latin1 string, free jchar array allocated by earlier call to GetStringCritical.
2910 // This assumes that ReleaseStringCritical bookends GetStringCritical.
2911 FREE_C_HEAP_ARRAY(chars);
2912 } else {
2913 // StringDedup can have replaced the value array, so don't fetch the array from 's'.
2914 // Instead, we calculate the address based on the jchar array exposed with GetStringCritical.
2915 oop value = cast_to_oop((address)chars - arrayOopDesc::base_offset_in_bytes(T_CHAR));
2916
2917 // Unpin value array
2918 Universe::heap()->unpin_object(thread, value);
2919 }
2920 thread->exit_jni_deferred_suspension();
2921 HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN();
2922 JNI_END
2923
2924
2925 JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
2926 HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref);
2927 Handle ref_handle(thread, JNIHandles::resolve(ref));
2928 jweak ret = JNIHandles::make_weak_global(ref_handle, AllocFailStrategy::RETURN_NULL);
2929 if (ret == nullptr && ref_handle.not_null()) {
2930 THROW_OOP_(Universe::out_of_memory_error_c_heap(), nullptr);
2931 }
2932 HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret);
2933 return ret;
2934 JNI_END
2935
2936 // Must be JNI_ENTRY (with HandleMark)
2937 JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))
2938 HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(env, ref);
2939 JNIHandles::destroy_weak_global(ref);
2940 HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN();
2941 JNI_END
2942
2943
2944 JNI_ENTRY_NO_PRESERVE(jboolean, jni_ExceptionCheck(JNIEnv *env))
2945 HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(env);
2946 jni_check_async_exceptions(thread);
2947 jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE;
3142
3143
3144 JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
3145 HOTSPOT_JNI_GETMODULE_ENTRY(env, clazz);
3146 jobject ret = Modules::get_module(clazz, THREAD);
3147 HOTSPOT_JNI_GETMODULE_RETURN(ret);
3148 return ret;
3149 JNI_END
3150
3151 JNI_ENTRY(jboolean, jni_IsVirtualThread(JNIEnv* env, jobject obj))
3152 HOTSPOT_JNI_ISVIRTUALTHREAD_ENTRY(env, obj);
3153 jboolean ret = JNI_FALSE;
3154 oop thread_obj = JNIHandles::resolve_external_guard(obj);
3155 if (thread_obj != nullptr && thread_obj->is_a(vmClasses::BaseVirtualThread_klass())) {
3156 ret = JNI_TRUE;
3157 }
3158 HOTSPOT_JNI_ISVIRTUALTHREAD_RETURN(ret);
3159 return ret;
3160 JNI_END
3161
3162
3163 // Structure containing all jni functions
3164 struct JNINativeInterface_ jni_NativeInterface = {
3165 nullptr,
3166 nullptr,
3167 nullptr,
3168
3169 nullptr,
3170
3171 jni_GetVersion,
3172
3173 jni_DefineClass,
3174 jni_FindClass,
3175
3176 jni_FromReflectedMethod,
3177 jni_FromReflectedField,
3178
3179 jni_ToReflectedMethod,
3180
3181 jni_GetSuperclass,
3434 jni_ExceptionCheck,
3435
3436 jni_NewDirectByteBuffer,
3437 jni_GetDirectBufferAddress,
3438 jni_GetDirectBufferCapacity,
3439
3440 // New 1_6 features
3441
3442 jni_GetObjectRefType,
3443
3444 // Module features
3445
3446 jni_GetModule,
3447
3448 // Virtual threads
3449
3450 jni_IsVirtualThread,
3451
3452 // Large UTF8 support
3453
3454 jni_GetStringUTFLengthAsLong
3455 };
3456
3457
3458 // For jvmti use to modify jni function table.
3459 // Java threads in native contiues to run until it is transitioned
3460 // to VM at safepoint. Before the transition or before it is blocked
3461 // for safepoint it may access jni function table. VM could crash if
3462 // any java thread access the jni function table in the middle of memcpy.
3463 // To avoid this each function pointers are copied automically.
3464 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
3465 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
3466 intptr_t *a = (intptr_t *) jni_functions();
3467 intptr_t *b = (intptr_t *) new_jni_NativeInterface;
3468 for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
3469 AtomicAccess::store(a++, *b++);
3470 }
3471 }
3472
3473 void quicken_jni_functions() {
3474 // Replace Get<Primitive>Field with fast versions
|
33 #include "classfile/javaThreadStatus.hpp"
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.inline.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/oopCast.inline.hpp"
65 #include "oops/symbol.hpp"
66 #include "oops/typeArrayKlass.hpp"
67 #include "oops/typeArrayOop.inline.hpp"
68 #include "oops/valuePayload.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/atomicAccess.hpp"
77 #include "runtime/fieldDescriptor.inline.hpp"
78 #include "runtime/handles.inline.hpp"
79 #include "runtime/interfaceSupport.inline.hpp"
80 #include "runtime/java.hpp"
81 #include "runtime/javaCalls.hpp"
82 #include "runtime/javaThread.inline.hpp"
83 #include "runtime/jfieldIDWorkaround.hpp"
84 #include "runtime/jniHandles.inline.hpp"
85 #include "runtime/reflection.hpp"
86 #include "runtime/safepointVerifiers.hpp"
87 #include "runtime/sharedRuntime.hpp"
88 #include "runtime/signature.hpp"
402 int modifiers = java_lang_reflect_Field::modifiers(reflected);
403
404 // Make sure class is initialized before handing id's out to fields
405 k1->initialize(CHECK_NULL);
406
407 // First check if this is a static field
408 if (modifiers & JVM_ACC_STATIC) {
409 int offset = InstanceKlass::cast(k1)->field_offset( slot );
410 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
411 assert(id != nullptr, "corrupt Field object");
412 DEBUG_ONLY(id->set_is_static_field_id();)
413 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
414 ret = jfieldIDWorkaround::to_static_jfieldID(id);
415 return ret;
416 }
417
418 // The slot is the index of the field description in the field-array
419 // The jfieldID is the offset of the field within the object
420 // It may also have hash bits for k, if VerifyJNIFields is turned on.
421 int offset = InstanceKlass::cast(k1)->field_offset( slot );
422 bool is_flat = InstanceKlass::cast(k1)->field_is_flat(slot);
423 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
424 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_flat);
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_constructor()) {
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);
1754 // table. If they're not there, the field doesn't exist.
1755 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1756 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1757 if (fieldname == nullptr || signame == nullptr) {
1758 ResourceMark rm;
1759 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1760 }
1761
1762 // Make sure class is initialized before handing id's out to fields
1763 k->initialize(CHECK_NULL);
1764
1765 fieldDescriptor fd;
1766 if (!k->is_instance_klass() ||
1767 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1768 ResourceMark rm;
1769 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1770 }
1771
1772 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1773 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1774 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flat());
1775 return ret;
1776 JNI_END
1777
1778
1779 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1780 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1781 oop o = JNIHandles::resolve_non_null(obj);
1782 Klass* k = o->klass();
1783 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1784 oop res = nullptr;
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 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1791 res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1792 } else {
1793 InstanceKlass* ik = InstanceKlass::cast(k);
1794 fieldDescriptor fd;
1795 bool found = ik->find_field_from_offset(offset, false, &fd); // performance bottleneck
1796 assert(found, "Field not found");
1797 FlatFieldPayload payload(instanceOop(o), &fd);
1798 res = payload.read(CHECK_NULL);
1799 }
1800 jobject ret = JNIHandles::make_local(THREAD, res);
1801 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1802 return ret;
1803 JNI_END
1804
1805
1806
1807 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1808 , EntryProbe, ReturnProbe) \
1809 \
1810 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1811 , ReturnProbe); \
1812 \
1813 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1814 \
1815 EntryProbe; \
1816 Return ret = 0;\
1817 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1818 \
1819 oop o = JNIHandles::resolve_non_null(obj); \
1820 Klass* k = o->klass(); \
1898 assert(found, "bad field offset");
1899 assert(!fd.is_static(), "static/instance mismatch");
1900 if (fd.is_final()) {
1901 ResourceMark rm(current);
1902 log_debug(jni)("%s mutated final instance field %s.%s", func_name, ik->external_name(), fd.name()->as_C_string());
1903 }
1904 }
1905 }
1906
1907 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1908 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1909 oop o = JNIHandles::resolve_non_null(obj);
1910 Klass* k = o->klass();
1911 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1912 // Keep JVMTI addition small and only check enabled flag here.
1913 if (JvmtiExport::should_post_field_modification()) {
1914 jvalue field_value;
1915 field_value.l = value;
1916 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1917 }
1918 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1919 oop v = JNIHandles::resolve(value);
1920 if (v == nullptr) {
1921 InstanceKlass *ik = InstanceKlass::cast(k);
1922 fieldDescriptor fd;
1923 ik->find_field_from_offset(offset, false, &fd);
1924 if (fd.is_null_free_inline_type()) {
1925 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Cannot store null in a null-restricted field");
1926 }
1927 }
1928 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, v);
1929 } else {
1930 assert(k->is_instance_klass(), "Only instances can have flat fields");
1931 InstanceKlass* ik = InstanceKlass::cast(k);
1932 fieldDescriptor fd;
1933 bool found = ik->find_field_from_offset(offset, false, &fd);
1934 assert(found, "Field not found");
1935 FlatFieldPayload payload(instanceOop(o), &fd);
1936 payload.write(inlineOop(JNIHandles::resolve(value)), CHECK);
1937 }
1938 log_debug_if_final_instance_field(thread, "SetObjectField", InstanceKlass::cast(k), offset);
1939 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1940 JNI_END
1941
1942 // TODO: make this a template
1943
1944 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1945 , EntryProbe, ReturnProbe) \
1946 \
1947 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1948 \
1949 EntryProbe; \
1950 \
1951 oop o = JNIHandles::resolve_non_null(obj); \
1952 Klass* k = o->klass(); \
1953 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1954 /* Keep JVMTI addition small and only check enabled flag here. */ \
1955 if (JvmtiExport::should_post_field_modification()) { \
1956 jvalue field_value; \
1957 field_value.unionType = value; \
2348 ek->initialize(CHECK_NULL);
2349 objArrayOop result = oopFactory::new_objArray(ek, length, CHECK_NULL);
2350
2351 oop initial_value = JNIHandles::resolve(initialElement);
2352 if (initial_value != nullptr) { // array already initialized with null
2353 for (int index = 0; index < length; index++) {
2354 result->obj_at_put(index, initial_value);
2355 }
2356 }
2357 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2358 return ret;
2359 JNI_END
2360
2361 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2362 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2363
2364 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2365 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2366 jobject ret = nullptr;
2367 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2368 objArrayOop a = oop_cast<objArrayOop>(JNIHandles::resolve_non_null(array));
2369 if (a->is_within_bounds(index)) {
2370 oop res = a->obj_at(index, CHECK_NULL);
2371 assert(res != nullptr || !a->is_null_free_array(), "Invalid value");
2372 ret = JNIHandles::make_local(THREAD, res);
2373 return ret;
2374 } else {
2375 ResourceMark rm(THREAD);
2376 stringStream ss;
2377 ss.print("Index %d out of bounds for length %d", index, a->length());
2378 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2379 }
2380 JNI_END
2381
2382 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2383 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2384
2385 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2386 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2387 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2388
2389 objArrayOop a = oop_cast<objArrayOop>(JNIHandles::resolve_non_null(array));
2390 oop v = JNIHandles::resolve(value);
2391 if (a->is_within_bounds(index)) {
2392 assert(a->klass()->is_refined_objArray_klass(), "must be");
2393 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2394 a->obj_at_put(index, v, THREAD);
2395 return;
2396 } else {
2397 ResourceMark rm(THREAD);
2398 stringStream ss;
2399 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2400 ss.print("type mismatch: can not store %s to %s[%d]",
2401 v->klass()->external_name(),
2402 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2403 index);
2404 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2405 ss.print("[]");
2406 }
2407 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2408 }
2409 } else {
2410 ResourceMark rm(THREAD);
2411 stringStream ss;
2412 ss.print("Index %d out of bounds for length %d", index, a->length());
2413 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2414 }
2415 JNI_END
2770 JNI_END
2771
2772 //
2773 // Monitor functions
2774 //
2775
2776 DT_RETURN_MARK_DECL(MonitorEnter, jint
2777 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2778
2779 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2780 HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2781 jint ret = JNI_ERR;
2782 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2783
2784 // If the object is null, we can't do anything with it
2785 if (jobj == nullptr) {
2786 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2787 }
2788
2789 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2790 ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
2791 return JNI_OK;
2792 JNI_END
2793
2794 DT_RETURN_MARK_DECL(MonitorExit, jint
2795 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2796
2797 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2798 HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2799 jint ret = JNI_ERR;
2800 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2801
2802 // Don't do anything with a null object
2803 if (jobj == nullptr) {
2804 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2805 }
2806
2807 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2808 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2809 return JNI_OK;
2810 JNI_END
2946 if (is_latin1) {
2947 // For latin1 string, free jchar array allocated by earlier call to GetStringCritical.
2948 // This assumes that ReleaseStringCritical bookends GetStringCritical.
2949 FREE_C_HEAP_ARRAY(chars);
2950 } else {
2951 // StringDedup can have replaced the value array, so don't fetch the array from 's'.
2952 // Instead, we calculate the address based on the jchar array exposed with GetStringCritical.
2953 oop value = cast_to_oop((address)chars - arrayOopDesc::base_offset_in_bytes(T_CHAR));
2954
2955 // Unpin value array
2956 Universe::heap()->unpin_object(thread, value);
2957 }
2958 thread->exit_jni_deferred_suspension();
2959 HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN();
2960 JNI_END
2961
2962
2963 JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
2964 HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref);
2965 Handle ref_handle(thread, JNIHandles::resolve(ref));
2966
2967 if (!ref_handle.is_null() && ref_handle->klass()->is_inline_klass()) {
2968 ResourceMark rm(THREAD);
2969 stringStream ss;
2970 ss.print("%s is not an identity class", ref_handle->klass()->external_name());
2971 THROW_MSG_(vmSymbols::java_lang_IdentityException(), ss.as_string(), nullptr);
2972 }
2973
2974 jweak ret = JNIHandles::make_weak_global(ref_handle, AllocFailStrategy::RETURN_NULL);
2975 if (ret == nullptr && ref_handle.not_null()) {
2976 THROW_OOP_(Universe::out_of_memory_error_c_heap(), nullptr);
2977 }
2978 HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret);
2979 return ret;
2980 JNI_END
2981
2982 // Must be JNI_ENTRY (with HandleMark)
2983 JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))
2984 HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(env, ref);
2985 JNIHandles::destroy_weak_global(ref);
2986 HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN();
2987 JNI_END
2988
2989
2990 JNI_ENTRY_NO_PRESERVE(jboolean, jni_ExceptionCheck(JNIEnv *env))
2991 HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(env);
2992 jni_check_async_exceptions(thread);
2993 jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE;
3188
3189
3190 JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
3191 HOTSPOT_JNI_GETMODULE_ENTRY(env, clazz);
3192 jobject ret = Modules::get_module(clazz, THREAD);
3193 HOTSPOT_JNI_GETMODULE_RETURN(ret);
3194 return ret;
3195 JNI_END
3196
3197 JNI_ENTRY(jboolean, jni_IsVirtualThread(JNIEnv* env, jobject obj))
3198 HOTSPOT_JNI_ISVIRTUALTHREAD_ENTRY(env, obj);
3199 jboolean ret = JNI_FALSE;
3200 oop thread_obj = JNIHandles::resolve_external_guard(obj);
3201 if (thread_obj != nullptr && thread_obj->is_a(vmClasses::BaseVirtualThread_klass())) {
3202 ret = JNI_TRUE;
3203 }
3204 HOTSPOT_JNI_ISVIRTUALTHREAD_RETURN(ret);
3205 return ret;
3206 JNI_END
3207
3208 JNI_ENTRY(jboolean, jni_HasIdentity(JNIEnv* env, jobject obj))
3209 HOTSPOT_JNI_HASIDENTITY_ENTRY(env, obj);
3210 oop o = JNIHandles::resolve(obj);
3211 if (o != nullptr && !o->klass()->is_inline_klass()) {
3212 HOTSPOT_JNI_HASIDENTITY_RETURN(JNI_TRUE);
3213 return JNI_TRUE;
3214 } else {
3215 HOTSPOT_JNI_HASIDENTITY_RETURN(JNI_FALSE);
3216 return JNI_FALSE;
3217 }
3218 JNI_END
3219
3220 // Structure containing all jni functions
3221 struct JNINativeInterface_ jni_NativeInterface = {
3222 nullptr,
3223 nullptr,
3224 nullptr,
3225
3226 nullptr,
3227
3228 jni_GetVersion,
3229
3230 jni_DefineClass,
3231 jni_FindClass,
3232
3233 jni_FromReflectedMethod,
3234 jni_FromReflectedField,
3235
3236 jni_ToReflectedMethod,
3237
3238 jni_GetSuperclass,
3491 jni_ExceptionCheck,
3492
3493 jni_NewDirectByteBuffer,
3494 jni_GetDirectBufferAddress,
3495 jni_GetDirectBufferCapacity,
3496
3497 // New 1_6 features
3498
3499 jni_GetObjectRefType,
3500
3501 // Module features
3502
3503 jni_GetModule,
3504
3505 // Virtual threads
3506
3507 jni_IsVirtualThread,
3508
3509 // Large UTF8 support
3510
3511 jni_GetStringUTFLengthAsLong,
3512
3513 // Value classes
3514
3515 jni_HasIdentity
3516 };
3517
3518
3519 // For jvmti use to modify jni function table.
3520 // Java threads in native contiues to run until it is transitioned
3521 // to VM at safepoint. Before the transition or before it is blocked
3522 // for safepoint it may access jni function table. VM could crash if
3523 // any java thread access the jni function table in the middle of memcpy.
3524 // To avoid this each function pointers are copied automically.
3525 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
3526 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
3527 intptr_t *a = (intptr_t *) jni_functions();
3528 intptr_t *b = (intptr_t *) new_jni_NativeInterface;
3529 for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
3530 AtomicAccess::store(a++, *b++);
3531 }
3532 }
3533
3534 void quicken_jni_functions() {
3535 // Replace Get<Primitive>Field with fast versions
|