Details
-
Bug
-
Status: Resolved
-
P4
-
Resolution: Fixed
-
None
-
b05
Description
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 (seeJDK-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. SeeJDK-8267879 for a case where ClassLoaderData::~ClassLoaderData() is called by ZGC while a safepoint is still in session.
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
Note: ZGC performs metadata deallocation outside of a safepoint. See
Attachments
Issue Links
- duplicates
-
JDK-8213466 Method::checked_resolve_jmethod_id() could do better checks
-
- Closed
-
- relates to
-
JDK-8267879 ClassLoaderMetaspace destructor asserts on !_frozen
-
- Resolved
-
-
JDK-8268406 Deallocate JNIMethodBlock when no JVMTI agents are loaded
-
- Open
-
-
JDK-8268088 Clarify Method::clear_jmethod_ids() related comments in ClassLoaderData::~ClassLoaderData()
-
- Resolved
-
-
JDK-8227410 jvmti/scenarios/hotswap/HS101/hs101t005 crashes with SIGSEGV
-
- Resolved
-
(2 links to)