On Mon, 23 Jun 2025 12:17:08 GMT, Coleen Phillimore <[email protected]> wrote:
> I'm not sure but I think in this instance, the native caller has the mirror
> for the class where it gets the jmethodID from, so can't unload the Method.
>
> ```
> JNI_ENTRY(ResultType, \
> jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID
> methodID, ...)) \
> \
> ```
@coleenp Take a look a the complete code:
JNI_ENTRY(ResultType, \
jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID
methodID, ...)) \
\
EntryProbe; \
ResultType ret{}; \
DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \
(const ResultType&)ret);\
\
va_list args; \
va_start(args, methodID); \
JavaValue jvalue(Tag); \
JNI_ArgumentPusherVaArg ap(methodID, args); \
jni_invoke_static(env, &jvalue, nullptr, JNI_STATIC, methodID, &ap,
CHECK_(ResultType{})); \
va_end(args); \
ret = jvalue.get_##ResultType(); \
return ret;\
JNI_END
the `cls` parameter is never actually used. So while it is supposed to refer to
the class you have the static method jMethodID for, there is no requirement
that it actually does, and could even be null.
> Once Method::resolve_jmethod_id(method_id) returns to the caller, how can the
> class be unreferenced?
@dcubed-ojdk because the caller does not hold a reference to it initially, and
resolving the jMethodID does not create a new reference to it. So once we have
resolved, at the next safepoint the class could be seen as "not alive" and at
the safepoint after that it can be unloaded. Hence we are relying on there
being no safepoint checks in the upcall code, after the resolution, to ensure
this can't happen.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/25267#issuecomment-2998571489