8275800: Redefinition leaks MethodData::_extra_data_lock

Reviewed-by: sspitsyn, dholmes
This commit is contained in:
Coleen Phillimore 2021-10-27 12:09:46 +00:00
parent 485d65865e
commit 40606021ee
5 changed files with 19 additions and 24 deletions

View File

@ -583,7 +583,10 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// Release C heap allocated data that this points to, which includes
// reference counting symbol names.
release_C_heap_structures_internal();
// Can't release the constant pool here because the constant pool can be
// deallocated separately from the InstanceKlass for default methods and
// redefine classes.
release_C_heap_structures(/* release_constant_pool */ false);
deallocate_methods(loader_data, methods());
set_methods(NULL);
@ -1638,7 +1641,8 @@ bool InstanceKlass::find_field_from_offset(int offset, bool is_static, fieldDesc
void InstanceKlass::methods_do(void f(Method* method)) {
// Methods aren't stable until they are loaded. This can be read outside
// a lock through the ClassLoaderData for profiling
if (!is_loaded()) {
// Redefined scratch classes are on the list and need to be cleaned
if (!is_loaded() && !is_scratch_class()) {
return;
}
@ -2681,22 +2685,13 @@ static void method_release_C_heap_structures(Method* m) {
m->release_C_heap_structures();
}
void InstanceKlass::release_C_heap_structures() {
// Called also by InstanceKlass::deallocate_contents, with false for release_constant_pool.
void InstanceKlass::release_C_heap_structures(bool release_constant_pool) {
// Clean up C heap
release_C_heap_structures_internal();
constants()->release_C_heap_structures();
Klass::release_C_heap_structures();
// Deallocate and call destructors for MDO mutexes
methods_do(method_release_C_heap_structures);
}
void InstanceKlass::release_C_heap_structures_internal() {
Klass::release_C_heap_structures();
// Can't release the constant pool here because the constant pool can be
// deallocated separately from the InstanceKlass for default methods and
// redefine classes.
// Deallocate oop map cache
if (_oop_map_cache != NULL) {
@ -2732,6 +2727,10 @@ void InstanceKlass::release_C_heap_structures_internal() {
#endif
FREE_C_HEAP_ARRAY(char, _source_debug_extension);
if (release_constant_pool) {
constants()->release_C_heap_structures();
}
}
void InstanceKlass::set_source_debug_extension(const char* array, int length) {
@ -3988,8 +3987,6 @@ void InstanceKlass::purge_previous_version_list() {
// so will be deallocated during the next phase of class unloading.
log_trace(redefine, class, iklass, purge)
("previous version " INTPTR_FORMAT " is dead.", p2i(pv_node));
// For debugging purposes.
pv_node->set_is_scratch_class();
// Unlink from previous version list.
assert(pv_node->class_loader_data() == loader_data, "wrong loader_data");
InstanceKlass* next = pv_node->previous_versions();
@ -4104,8 +4101,6 @@ void InstanceKlass::add_previous_version(InstanceKlass* scratch_class,
ConstantPool* cp_ref = scratch_class->constants();
if (!cp_ref->on_stack()) {
log_trace(redefine, class, iklass, add)("scratch class not added; no methods are running");
// For debugging purposes.
scratch_class->set_is_scratch_class();
scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class);
return;
}

View File

@ -1101,7 +1101,7 @@ public:
// callbacks for actions during class unloading
static void unload_class(InstanceKlass* ik);
virtual void release_C_heap_structures();
virtual void release_C_heap_structures(bool release_constant_pool = true);
// Naming
const char* signature_name() const;
@ -1218,9 +1218,6 @@ private:
StaticLookupMode static_mode,
PrivateLookupMode private_mode);
// Free CHeap allocated fields.
void release_C_heap_structures_internal();
#if INCLUDE_JVMTI
// RedefineClasses support
void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }

View File

@ -105,7 +105,7 @@ bool Klass::is_subclass_of(const Klass* k) const {
return false;
}
void Klass::release_C_heap_structures() {
void Klass::release_C_heap_structures(bool release_constant_pool) {
if (_name != NULL) _name->decrement_refcount();
}

View File

@ -661,7 +661,7 @@ protected:
Symbol* name() const { return _name; }
void set_name(Symbol* n);
virtual void release_C_heap_structures();
virtual void release_C_heap_structures(bool release_constant_pool = true);
public:
virtual jint compute_modifier_flags() const = 0;

View File

@ -4404,6 +4404,9 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas
the_class->set_has_been_redefined();
// Scratch class is unloaded but still needs cleaning, and skipping for CDS.
scratch_class->set_is_scratch_class();
// keep track of previous versions of this class
the_class->add_previous_version(scratch_class, emcp_method_count);