8296955: Kitchensink.java failed with "double free or corruption (!prev): <addr>"

Reviewed-by: kbarrett, eosterlund, sspitsyn, dcubed
This commit is contained in:
Coleen Phillimore 2022-12-13 00:49:16 +00:00
parent 8962c723a8
commit d453190300
3 changed files with 39 additions and 75 deletions

View file

@ -2148,15 +2148,8 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) {
// the cache can't grow so we can just get the current values
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
} else {
// cache can grow so we have to be more careful
if (Threads::number_of_threads() == 0 ||
SafepointSynchronize::is_at_safepoint()) {
// we're single threaded or at a safepoint - no locking needed
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
} else {
MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag);
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
}
MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag);
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
}
}
// implied else:
@ -2166,8 +2159,8 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) {
length <= idnum || // cache is too short
id == NULL) { // cache doesn't contain entry
// This function can be called by the VMThread so we have to do all
// things that might block on a safepoint before grabbing the lock.
// This function can be called by the VMThread or GC worker threads so we
// have to do all things that might block on a safepoint before grabbing the lock.
// Otherwise, we can deadlock with the VMThread or have a cache
// consistency issue. These vars keep track of what we might have
// to free after the lock is dropped.
@ -2186,25 +2179,20 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) {
}
// allocate a new jmethodID that might be used
jmethodID new_id = NULL;
if (method_h->is_old() && !method_h->is_obsolete()) {
// The method passed in is old (but not obsolete), we need to use the current version
Method* current_method = method_with_idnum((int)idnum);
assert(current_method != NULL, "old and but not obsolete, so should exist");
new_id = Method::make_jmethod_id(class_loader_data(), current_method);
} else {
// It is the current version of the method or an obsolete method,
// use the version passed in
new_id = Method::make_jmethod_id(class_loader_data(), method_h());
}
if (Threads::number_of_threads() == 0 ||
SafepointSynchronize::is_at_safepoint()) {
// we're single threaded or at a safepoint - no locking needed
id = get_jmethod_id_fetch_or_update(idnum, new_id, new_jmeths,
&to_dealloc_id, &to_dealloc_jmeths);
} else {
{
MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag);
jmethodID new_id = NULL;
if (method_h->is_old() && !method_h->is_obsolete()) {
// The method passed in is old (but not obsolete), we need to use the current version
Method* current_method = method_with_idnum((int)idnum);
assert(current_method != NULL, "old and but not obsolete, so should exist");
new_id = Method::make_jmethod_id(class_loader_data(), current_method);
} else {
// It is the current version of the method or an obsolete method,
// use the version passed in
new_id = Method::make_jmethod_id(class_loader_data(), method_h());
}
id = get_jmethod_id_fetch_or_update(idnum, new_id, new_jmeths,
&to_dealloc_id, &to_dealloc_jmeths);
}
@ -2254,9 +2242,7 @@ jmethodID InstanceKlass::get_jmethod_id_fetch_or_update(
assert(new_id != NULL, "sanity check");
assert(to_dealloc_id_p != NULL, "sanity check");
assert(to_dealloc_jmeths_p != NULL, "sanity check");
assert(Threads::number_of_threads() == 0 ||
SafepointSynchronize::is_at_safepoint() ||
JmethodIdCreation_lock->owned_by_self(), "sanity check");
assert(JmethodIdCreation_lock->owned_by_self(), "sanity check");
// reacquire the cache - we are locked, single threaded or at a safepoint
jmethodID* jmeths = methods_jmethod_ids_acquire();