< 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"

 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
< prev index next >