JDK 17 | JDK 18 |
---|---|
17.0.14Fixed | 18 b05Fixed |
Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
jmethodIDs are basically handles of Method*. In generated JVMTI functions such as jvmti_GetMethodDeclaringClass, we will first check if a jmethodID is valid (i.e., if it contains a non-NULL Method*). If so, we will dereference the Method*: =================================== jvmti_GetMethodDeclaringClass(jvmtiEnv* env, jmethodID method, jclass* declaring_class_ptr) { if(JvmtiEnv::get_phase(env)!=JVMTI_PHASE_START && JvmtiEnv::get_phase()!=JVMTI_PHASE_LIVE) { return JVMTI_ERROR_WRONG_PHASE; } Thread* this_thread = Thread::current_or_null(); if (this_thread == NULL || !this_thread->is_Java_thread()) { return JVMTI_ERROR_UNATTACHED_THREAD; } JavaThread* current_thread = this_thread->as_Java_thread(); MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current_thread)); ThreadInVMfromNative __tiv(current_thread); VM_ENTRY_BASE(jvmtiError, jvmti_GetMethodDeclaringClass , current_thread) debug_only(VMNativeEntryWrapper __vew;) PreserveExceptionMark __em(this_thread); JvmtiEnv* jvmti_env = JvmtiEnv::JvmtiEnv_from_jvmti_env(env); if (!jvmti_env->is_valid()) { return JVMTI_ERROR_INVALID_ENVIRONMENT; } jvmtiError err; Method* checked_method = Method::checked_resolve_jmethod_id(method); if (checked_method == NULL) { return JVMTI_ERROR_INVALID_METHODID; } if (declaring_class_ptr == NULL) { return JVMTI_ERROR_NULL_POINTER; } <<<<<<< ZGC can concurrently deallocate the checked_method err = jvmti_env->GetMethodDeclaringClass(checked_method, declaring_class_ptr); <<<<< crash return err; } =================================== This in not compatible with GCs that perform concurrent class deallcation (such as ZGC). If <method> belongs to a class that has been collected (see JDK-8268088), but not yet deallocated, <checked_method> could be non-NULL, but will be concurrently deallocated by ZGC. So by the time we call into jvmti_env->GetMethodDeclaringClass, <checked_method> already points to bad memory. Note: ZGC performs metadata deallocation outside of a safepoint. See JDK-8267879 for a case where ClassLoaderData::~ClassLoaderData() is called by ZGC while a safepoint is still in session.
|