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

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

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









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

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



















1908   log_debug_if_final_instance_field(thread, "SetObjectField", InstanceKlass::cast(k), offset);
1909   HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1910 JNI_END
1911 
1912 // TODO: make this a template
1913 
1914 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1915                         , EntryProbe, ReturnProbe) \
1916 \
1917 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1918 \
1919   EntryProbe; \
1920 \
1921   oop o = JNIHandles::resolve_non_null(obj); \
1922   Klass* k = o->klass(); \
1923   int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);  \
1924   /* Keep JVMTI addition small and only check enabled flag here.       */ \
1925   if (JvmtiExport::should_post_field_modification()) { \
1926     jvalue field_value; \
1927     field_value.unionType = value; \

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


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

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

2362     } else {
2363       ResourceMark rm(THREAD);
2364       stringStream ss;
2365       Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2366       ss.print("type mismatch: can not store %s to %s[%d]",
2367                v->klass()->external_name(),
2368                bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2369                index);
2370       for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2371         ss.print("[]");
2372       }
2373       THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2374     }
2375   } else {
2376     ResourceMark rm(THREAD);
2377     stringStream ss;
2378     ss.print("Index %d out of bounds for length %d", index, a->length());
2379     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2380   }
2381 JNI_END

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

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








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

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











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

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




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

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

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

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

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

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

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

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