< prev index next >

src/hotspot/share/prims/jni.cpp

Print this page

  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"

 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);

1752   // table.  If they're not there, the field doesn't exist.
1753   TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1754   TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1755   if (fieldname == nullptr || signame == nullptr) {
1756     ResourceMark rm;
1757     THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1758   }
1759 
1760   // Make sure class is initialized before handing id's out to fields
1761   k->initialize(CHECK_NULL);
1762 
1763   fieldDescriptor fd;
1764   if (!k->is_instance_klass() ||
1765       !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1766     ResourceMark rm;
1767     THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1768   }
1769 
1770   // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1771   // It may also have hash bits for k, if VerifyJNIFields is turned on.
1772   ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
1773   return ret;
1774 JNI_END
1775 
1776 
1777 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1778   HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1779   oop o = JNIHandles::resolve_non_null(obj);
1780   Klass* k = o->klass();
1781   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);

1782   // Keep JVMTI addition small and only check enabled flag here.
1783   // jni_GetField_probe() assumes that is okay to create handles.
1784   if (JvmtiExport::should_post_field_access()) {
1785     o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1786   }
1787   oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1788   jobject ret = JNIHandles::make_local(THREAD, loaded_obj);









1789   HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1790   return ret;
1791 JNI_END
1792 
1793 
1794 
1795 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1796   , EntryProbe, ReturnProbe) \
1797 \
1798   DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1799   , ReturnProbe); \
1800 \
1801 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1802 \
1803   EntryProbe; \
1804   Return ret = 0;\
1805   DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1806 \
1807   oop o = JNIHandles::resolve_non_null(obj); \
1808   Klass* k = o->klass(); \

1886     assert(found, "bad field offset");
1887     assert(!fd.is_static(), "static/instance mismatch");
1888     if (fd.is_final()) {
1889       ResourceMark rm(current);
1890       log_debug(jni)("%s mutated final instance field %s.%s", func_name, ik->external_name(), fd.name()->as_C_string());
1891     }
1892   }
1893 }
1894 
1895 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1896   HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1897   oop o = JNIHandles::resolve_non_null(obj);
1898   Klass* k = o->klass();
1899   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1900   // Keep JVMTI addition small and only check enabled flag here.
1901   if (JvmtiExport::should_post_field_modification()) {
1902     jvalue field_value;
1903     field_value.l = value;
1904     o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1905   }
1906   HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));



















1907   log_debug_if_final_instance_field(thread, "SetObjectField", InstanceKlass::cast(k), offset);
1908   HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1909 JNI_END
1910 
1911 // TODO: make this a template
1912 
1913 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1914                         , EntryProbe, ReturnProbe) \
1915 \
1916 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1917 \
1918   EntryProbe; \
1919 \
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.unionType = value; \

2317   ek->initialize(CHECK_NULL);
2318   objArrayOop result = oopFactory::new_objArray(ek, length, CHECK_NULL);
2319 
2320   oop initial_value = JNIHandles::resolve(initialElement);
2321   if (initial_value != nullptr) {  // array already initialized with null
2322     for (int index = 0; index < length; index++) {
2323       result->obj_at_put(index, initial_value);
2324     }
2325   }
2326   ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2327   return ret;
2328 JNI_END
2329 
2330 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2331                     , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2332 
2333 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2334  HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2335   jobject ret = nullptr;
2336   DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2337   objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2338   if (a->is_within_bounds(index)) {
2339     ret = JNIHandles::make_local(THREAD, a->obj_at(index));


2340     return ret;
2341   } else {
2342     ResourceMark rm(THREAD);
2343     stringStream ss;
2344     ss.print("Index %d out of bounds for length %d", index, a->length());
2345     THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2346   }
2347 JNI_END
2348 
2349 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2350                          , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2351 
2352 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2353  HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2354   DT_VOID_RETURN_MARK(SetObjectArrayElement);
2355 
2356   objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2357   oop v = JNIHandles::resolve(value);
2358   if (a->is_within_bounds(index)) {

2359     if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2360       a->obj_at_put(index, v);

2361     } else {
2362       ResourceMark rm(THREAD);
2363       stringStream ss;
2364       Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2365       ss.print("type mismatch: can not store %s to %s[%d]",
2366                v->klass()->external_name(),
2367                bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2368                index);
2369       for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2370         ss.print("[]");
2371       }
2372       THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2373     }
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(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2379   }
2380 JNI_END

2735 JNI_END
2736 
2737 //
2738 // Monitor functions
2739 //
2740 
2741 DT_RETURN_MARK_DECL(MonitorEnter, jint
2742                     , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2743 
2744 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2745  HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2746   jint ret = JNI_ERR;
2747   DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2748 
2749   // If the object is null, we can't do anything with it
2750   if (jobj == nullptr) {
2751     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2752   }
2753 
2754   Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2755   ObjectSynchronizer::jni_enter(obj, thread);
2756   return JNI_OK;
2757 JNI_END
2758 
2759 DT_RETURN_MARK_DECL(MonitorExit, jint
2760                     , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2761 
2762 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2763  HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2764   jint ret = JNI_ERR;
2765   DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2766 
2767   // Don't do anything with a null object
2768   if (jobj == nullptr) {
2769     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2770   }
2771 
2772   Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2773   ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2774   return JNI_OK;
2775 JNI_END

2894 
2895   if (is_latin1) {
2896     // For latin1 string, free jchar array allocated by earlier call to GetStringCritical.
2897     // This assumes that ReleaseStringCritical bookends GetStringCritical.
2898     FREE_C_HEAP_ARRAY(chars);
2899   } else {
2900     // StringDedup can have replaced the value array, so don't fetch the array from 's'.
2901     // Instead, we calculate the address based on the jchar array exposed with GetStringCritical.
2902     oop value = cast_to_oop((address)chars - arrayOopDesc::base_offset_in_bytes(T_CHAR));
2903 
2904     // Unpin value array
2905     Universe::heap()->unpin_object(thread, value);
2906   }
2907 HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN();
2908 JNI_END
2909 
2910 
2911 JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
2912   HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref);
2913   Handle ref_handle(thread, JNIHandles::resolve(ref));








2914   jweak ret = JNIHandles::make_weak_global(ref_handle, AllocFailStrategy::RETURN_NULL);
2915   if (ret == nullptr && ref_handle.not_null()) {
2916     THROW_OOP_(Universe::out_of_memory_error_c_heap(), nullptr);
2917   }
2918   HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret);
2919   return ret;
2920 JNI_END
2921 
2922 // Must be JNI_ENTRY (with HandleMark)
2923 JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))
2924   HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(env, ref);
2925   JNIHandles::destroy_weak_global(ref);
2926   HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN();
2927 JNI_END
2928 
2929 
2930 JNI_ENTRY_NO_PRESERVE(jboolean, jni_ExceptionCheck(JNIEnv *env))
2931  HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(env);
2932   jni_check_async_exceptions(thread);
2933   jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE;

3128 
3129 
3130 JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
3131   HOTSPOT_JNI_GETMODULE_ENTRY(env, clazz);
3132   jobject ret = Modules::get_module(clazz, THREAD);
3133   HOTSPOT_JNI_GETMODULE_RETURN(ret);
3134   return ret;
3135 JNI_END
3136 
3137 JNI_ENTRY(jboolean, jni_IsVirtualThread(JNIEnv* env, jobject obj))
3138   HOTSPOT_JNI_ISVIRTUALTHREAD_ENTRY(env, obj);
3139   jboolean ret = JNI_FALSE;
3140   oop thread_obj = JNIHandles::resolve_external_guard(obj);
3141   if (thread_obj != nullptr && thread_obj->is_a(vmClasses::BaseVirtualThread_klass())) {
3142     ret = JNI_TRUE;
3143   }
3144   HOTSPOT_JNI_ISVIRTUALTHREAD_RETURN(ret);
3145   return ret;
3146 JNI_END
3147 











3148 
3149 // Structure containing all jni functions
3150 struct JNINativeInterface_ jni_NativeInterface = {
3151     nullptr,
3152     nullptr,
3153     nullptr,
3154 
3155     nullptr,
3156 
3157     jni_GetVersion,
3158 
3159     jni_DefineClass,
3160     jni_FindClass,
3161 
3162     jni_FromReflectedMethod,
3163     jni_FromReflectedField,
3164 
3165     jni_ToReflectedMethod,
3166 
3167     jni_GetSuperclass,

3420     jni_ExceptionCheck,
3421 
3422     jni_NewDirectByteBuffer,
3423     jni_GetDirectBufferAddress,
3424     jni_GetDirectBufferCapacity,
3425 
3426     // New 1_6 features
3427 
3428     jni_GetObjectRefType,
3429 
3430     // Module features
3431 
3432     jni_GetModule,
3433 
3434     // Virtual threads
3435 
3436     jni_IsVirtualThread,
3437 
3438     // Large UTF8 support
3439 
3440     jni_GetStringUTFLengthAsLong




3441 };
3442 
3443 
3444 // For jvmti use to modify jni function table.
3445 // Java threads in native contiues to run until it is transitioned
3446 // to VM at safepoint. Before the transition or before it is blocked
3447 // for safepoint it may access jni function table. VM could crash if
3448 // any java thread access the jni function table in the middle of memcpy.
3449 // To avoid this each function pointers are copied automically.
3450 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
3451   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
3452   intptr_t *a = (intptr_t *) jni_functions();
3453   intptr_t *b = (intptr_t *) new_jni_NativeInterface;
3454   for (uint i=0; i <  sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
3455     AtomicAccess::store(a++, *b++);
3456   }
3457 }
3458 
3459 void quicken_jni_functions() {
3460   // 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"

 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);

1757   // table.  If they're not there, the field doesn't exist.
1758   TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1759   TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1760   if (fieldname == nullptr || signame == nullptr) {
1761     ResourceMark rm;
1762     THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1763   }
1764 
1765   // Make sure class is initialized before handing id's out to fields
1766   k->initialize(CHECK_NULL);
1767 
1768   fieldDescriptor fd;
1769   if (!k->is_instance_klass() ||
1770       !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1771     ResourceMark rm;
1772     THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1773   }
1774 
1775   // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1776   // It may also have hash bits for k, if VerifyJNIFields is turned on.
1777   ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flat());
1778   return ret;
1779 JNI_END
1780 
1781 
1782 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1783   HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1784   oop o = JNIHandles::resolve_non_null(obj);
1785   Klass* k = o->klass();
1786   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1787   oop res = nullptr;
1788   // Keep JVMTI addition small and only check enabled flag here.
1789   // jni_GetField_probe() assumes that is okay to create handles.
1790   if (JvmtiExport::should_post_field_access()) {
1791     o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1792   }
1793   if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1794     res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1795   } else {
1796     InstanceKlass* ik = InstanceKlass::cast(k);
1797     fieldDescriptor fd;
1798     bool found = ik->find_field_from_offset(offset, false, &fd);  // performance bottleneck
1799     assert(found, "Field not found");
1800     FlatFieldPayload payload(instanceOop(o), &fd);
1801     res = payload.read(CHECK_NULL);
1802   }
1803   jobject ret = JNIHandles::make_local(THREAD, res);
1804   HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1805   return ret;
1806 JNI_END
1807 
1808 
1809 
1810 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1811   , EntryProbe, ReturnProbe) \
1812 \
1813   DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1814   , ReturnProbe); \
1815 \
1816 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1817 \
1818   EntryProbe; \
1819   Return ret = 0;\
1820   DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1821 \
1822   oop o = JNIHandles::resolve_non_null(obj); \
1823   Klass* k = o->klass(); \

1901     assert(found, "bad field offset");
1902     assert(!fd.is_static(), "static/instance mismatch");
1903     if (fd.is_final()) {
1904       ResourceMark rm(current);
1905       log_debug(jni)("%s mutated final instance field %s.%s", func_name, ik->external_name(), fd.name()->as_C_string());
1906     }
1907   }
1908 }
1909 
1910 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1911   HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1912   oop o = JNIHandles::resolve_non_null(obj);
1913   Klass* k = o->klass();
1914   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1915   // Keep JVMTI addition small and only check enabled flag here.
1916   if (JvmtiExport::should_post_field_modification()) {
1917     jvalue field_value;
1918     field_value.l = value;
1919     o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1920   }
1921   if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1922     oop v = JNIHandles::resolve(value);
1923     if (v == nullptr) {
1924       InstanceKlass *ik = InstanceKlass::cast(k);
1925       fieldDescriptor fd;
1926       ik->find_field_from_offset(offset, false, &fd);
1927       if (fd.is_null_free_inline_type()) {
1928         THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Cannot store null in a null-restricted field");
1929       }
1930     }
1931     HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, v);
1932   } else {
1933     assert(k->is_instance_klass(), "Only instances can have flat fields");
1934     InstanceKlass* ik = InstanceKlass::cast(k);
1935     fieldDescriptor fd;
1936     bool found = ik->find_field_from_offset(offset, false, &fd);
1937     assert(found, "Field not found");
1938     FlatFieldPayload payload(instanceOop(o), &fd);
1939     payload.write(inlineOop(JNIHandles::resolve(value)), CHECK);
1940   }
1941   log_debug_if_final_instance_field(thread, "SetObjectField", InstanceKlass::cast(k), offset);
1942   HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1943 JNI_END
1944 
1945 // TODO: make this a template
1946 
1947 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1948                         , EntryProbe, ReturnProbe) \
1949 \
1950 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1951 \
1952   EntryProbe; \
1953 \
1954   oop o = JNIHandles::resolve_non_null(obj); \
1955   Klass* k = o->klass(); \
1956   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);  \
1957   /* Keep JVMTI addition small and only check enabled flag here.       */ \
1958   if (JvmtiExport::should_post_field_modification()) { \
1959     jvalue field_value; \
1960     field_value.unionType = value; \

2351   ek->initialize(CHECK_NULL);
2352   objArrayOop result = oopFactory::new_objArray(ek, length, CHECK_NULL);
2353 
2354   oop initial_value = JNIHandles::resolve(initialElement);
2355   if (initial_value != nullptr) {  // array already initialized with null
2356     for (int index = 0; index < length; index++) {
2357       result->obj_at_put(index, initial_value);
2358     }
2359   }
2360   ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2361   return ret;
2362 JNI_END
2363 
2364 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2365                     , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2366 
2367 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2368  HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2369   jobject ret = nullptr;
2370   DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2371   objArrayOop a = oop_cast<objArrayOop>(JNIHandles::resolve_non_null(array));
2372   if (a->is_within_bounds(index)) {
2373     oop res = a->obj_at(index, CHECK_NULL);
2374     assert(res != nullptr || !a->is_null_free_array(), "Invalid value");
2375     ret = JNIHandles::make_local(THREAD, res);
2376     return ret;
2377   } else {
2378     ResourceMark rm(THREAD);
2379     stringStream ss;
2380     ss.print("Index %d out of bounds for length %d", index, a->length());
2381     THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2382   }
2383 JNI_END
2384 
2385 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2386                          , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2387 
2388 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2389  HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2390   DT_VOID_RETURN_MARK(SetObjectArrayElement);
2391 
2392   objArrayOop a = oop_cast<objArrayOop>(JNIHandles::resolve_non_null(array));
2393   oop v = JNIHandles::resolve(value);
2394   if (a->is_within_bounds(index)) {
2395     assert(a->klass()->is_refined_objArray_klass(), "must be");
2396     if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2397       a->obj_at_put(index, v, THREAD);
2398       return;
2399     } else {
2400       ResourceMark rm(THREAD);
2401       stringStream ss;
2402       Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2403       ss.print("type mismatch: can not store %s to %s[%d]",
2404                v->klass()->external_name(),
2405                bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2406                index);
2407       for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2408         ss.print("[]");
2409       }
2410       THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2411     }
2412   } else {
2413     ResourceMark rm(THREAD);
2414     stringStream ss;
2415     ss.print("Index %d out of bounds for length %d", index, a->length());
2416     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2417   }
2418 JNI_END

2773 JNI_END
2774 
2775 //
2776 // Monitor functions
2777 //
2778 
2779 DT_RETURN_MARK_DECL(MonitorEnter, jint
2780                     , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
2781 
2782 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
2783  HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
2784   jint ret = JNI_ERR;
2785   DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
2786 
2787   // If the object is null, we can't do anything with it
2788   if (jobj == nullptr) {
2789     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2790   }
2791 
2792   Handle obj(thread, JNIHandles::resolve_non_null(jobj));
2793   ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
2794   return JNI_OK;
2795 JNI_END
2796 
2797 DT_RETURN_MARK_DECL(MonitorExit, jint
2798                     , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
2799 
2800 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
2801  HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
2802   jint ret = JNI_ERR;
2803   DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
2804 
2805   // Don't do anything with a null object
2806   if (jobj == nullptr) {
2807     THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
2808   }
2809 
2810   Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
2811   ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
2812   return JNI_OK;
2813 JNI_END

2932 
2933   if (is_latin1) {
2934     // For latin1 string, free jchar array allocated by earlier call to GetStringCritical.
2935     // This assumes that ReleaseStringCritical bookends GetStringCritical.
2936     FREE_C_HEAP_ARRAY(chars);
2937   } else {
2938     // StringDedup can have replaced the value array, so don't fetch the array from 's'.
2939     // Instead, we calculate the address based on the jchar array exposed with GetStringCritical.
2940     oop value = cast_to_oop((address)chars - arrayOopDesc::base_offset_in_bytes(T_CHAR));
2941 
2942     // Unpin value array
2943     Universe::heap()->unpin_object(thread, value);
2944   }
2945 HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN();
2946 JNI_END
2947 
2948 
2949 JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
2950   HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref);
2951   Handle ref_handle(thread, JNIHandles::resolve(ref));
2952 
2953   if (!ref_handle.is_null() && ref_handle->klass()->is_inline_klass()) {
2954     ResourceMark rm(THREAD);
2955     stringStream ss;
2956     ss.print("%s is not an identity class", ref_handle->klass()->external_name());
2957     THROW_MSG_(vmSymbols::java_lang_IdentityException(), ss.as_string(), nullptr);
2958   }
2959 
2960   jweak ret = JNIHandles::make_weak_global(ref_handle, AllocFailStrategy::RETURN_NULL);
2961   if (ret == nullptr && ref_handle.not_null()) {
2962     THROW_OOP_(Universe::out_of_memory_error_c_heap(), nullptr);
2963   }
2964   HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret);
2965   return ret;
2966 JNI_END
2967 
2968 // Must be JNI_ENTRY (with HandleMark)
2969 JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))
2970   HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(env, ref);
2971   JNIHandles::destroy_weak_global(ref);
2972   HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN();
2973 JNI_END
2974 
2975 
2976 JNI_ENTRY_NO_PRESERVE(jboolean, jni_ExceptionCheck(JNIEnv *env))
2977  HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(env);
2978   jni_check_async_exceptions(thread);
2979   jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE;

3174 
3175 
3176 JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
3177   HOTSPOT_JNI_GETMODULE_ENTRY(env, clazz);
3178   jobject ret = Modules::get_module(clazz, THREAD);
3179   HOTSPOT_JNI_GETMODULE_RETURN(ret);
3180   return ret;
3181 JNI_END
3182 
3183 JNI_ENTRY(jboolean, jni_IsVirtualThread(JNIEnv* env, jobject obj))
3184   HOTSPOT_JNI_ISVIRTUALTHREAD_ENTRY(env, obj);
3185   jboolean ret = JNI_FALSE;
3186   oop thread_obj = JNIHandles::resolve_external_guard(obj);
3187   if (thread_obj != nullptr && thread_obj->is_a(vmClasses::BaseVirtualThread_klass())) {
3188     ret = JNI_TRUE;
3189   }
3190   HOTSPOT_JNI_ISVIRTUALTHREAD_RETURN(ret);
3191   return ret;
3192 JNI_END
3193 
3194 JNI_ENTRY(jboolean, jni_IsValueObject(JNIEnv* env, jobject obj))
3195   HOTSPOT_JNI_ISVALUEOBJECT_ENTRY(env, obj);
3196   oop o = JNIHandles::resolve(obj);
3197   if (o != nullptr && o->klass()->is_inline_klass()) {
3198     HOTSPOT_JNI_ISVALUEOBJECT_RETURN(JNI_TRUE);
3199     return JNI_TRUE;
3200   } else {
3201     HOTSPOT_JNI_ISVALUEOBJECT_RETURN(JNI_FALSE);
3202     return JNI_FALSE;
3203   }
3204 JNI_END
3205 
3206 // Structure containing all jni functions
3207 struct JNINativeInterface_ jni_NativeInterface = {
3208     nullptr,
3209     nullptr,
3210     nullptr,
3211 
3212     nullptr,
3213 
3214     jni_GetVersion,
3215 
3216     jni_DefineClass,
3217     jni_FindClass,
3218 
3219     jni_FromReflectedMethod,
3220     jni_FromReflectedField,
3221 
3222     jni_ToReflectedMethod,
3223 
3224     jni_GetSuperclass,

3477     jni_ExceptionCheck,
3478 
3479     jni_NewDirectByteBuffer,
3480     jni_GetDirectBufferAddress,
3481     jni_GetDirectBufferCapacity,
3482 
3483     // New 1_6 features
3484 
3485     jni_GetObjectRefType,
3486 
3487     // Module features
3488 
3489     jni_GetModule,
3490 
3491     // Virtual threads
3492 
3493     jni_IsVirtualThread,
3494 
3495     // Large UTF8 support
3496 
3497     jni_GetStringUTFLengthAsLong,
3498 
3499     // Value classes
3500 
3501     jni_IsValueObject
3502 };
3503 
3504 
3505 // For jvmti use to modify jni function table.
3506 // Java threads in native contiues to run until it is transitioned
3507 // to VM at safepoint. Before the transition or before it is blocked
3508 // for safepoint it may access jni function table. VM could crash if
3509 // any java thread access the jni function table in the middle of memcpy.
3510 // To avoid this each function pointers are copied automically.
3511 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
3512   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
3513   intptr_t *a = (intptr_t *) jni_functions();
3514   intptr_t *b = (intptr_t *) new_jni_NativeInterface;
3515   for (uint i=0; i <  sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
3516     AtomicAccess::store(a++, *b++);
3517   }
3518 }
3519 
3520 void quicken_jni_functions() {
3521   // Replace Get<Primitive>Field with fast versions
< prev index next >