8243503: InstanceKlass::_array_name is not needed and leaks

Decrement the refcount for all Klass in class unloading.

Reviewed-by: lfoltan, hseigel
This commit is contained in:
Coleen Phillimore 2020-04-24 16:54:28 -04:00
parent 05bf8dced5
commit f8ab03fa04
6 changed files with 30 additions and 45 deletions

@ -640,8 +640,8 @@ public:
} else {
assert(k->is_instance_klass(), "Must be");
_instance_class_released ++;
InstanceKlass::release_C_heap_structures(InstanceKlass::cast(k));
}
k->release_C_heap_structures();
}
};
@ -869,7 +869,7 @@ void ClassLoaderData::free_deallocate_list_C_heap_structures() {
} else if (m->is_klass()) {
InstanceKlass* ik = (InstanceKlass*)m;
// also releases ik->constants() C heap memory
InstanceKlass::release_C_heap_structures(ik);
ik->release_C_heap_structures();
// Remove the class so unloading events aren't triggered for
// this class (scratch or error class) in do_unloading().
remove_class(ik);

@ -587,9 +587,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
// to deallocate.
assert(array_klasses() == NULL, "array classes shouldn't be created for this class yet");
// Release C heap allocated data that this might point to, which includes
// Release C heap allocated data that this points to, which includes
// reference counting symbol names.
release_C_heap_structures();
release_C_heap_structures_internal();
deallocate_methods(loader_data, methods());
set_methods(NULL);
@ -2386,7 +2386,6 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
it->push((Klass**)&_array_klasses);
it->push(&_constants);
it->push(&_inner_classes);
it->push(&_array_name);
#if INCLUDE_JVMTI
it->push(&_previous_versions);
#endif
@ -2581,17 +2580,19 @@ static void method_release_C_heap_structures(Method* m) {
m->release_C_heap_structures();
}
void InstanceKlass::release_C_heap_structures(InstanceKlass* ik) {
void InstanceKlass::release_C_heap_structures() {
// Clean up C heap
ik->release_C_heap_structures();
ik->constants()->release_C_heap_structures();
release_C_heap_structures_internal();
constants()->release_C_heap_structures();
// Deallocate and call destructors for MDO mutexes
ik->methods_do(method_release_C_heap_structures);
methods_do(method_release_C_heap_structures);
}
void InstanceKlass::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.
@ -2629,12 +2630,6 @@ void InstanceKlass::release_C_heap_structures() {
}
#endif
// Decrement symbol reference counts associated with the unloaded class.
if (_name != NULL) _name->decrement_refcount();
// unreference array name derived from this class name (arrays of an unloaded
// class can't be referenced anymore).
if (_array_name != NULL) _array_name->decrement_refcount();
FREE_C_HEAP_ARRAY(char, _source_debug_extension);
}

@ -205,9 +205,6 @@ class InstanceKlass: public Klass {
// Specified as UTF-8 string without terminating zero byte in the classfile,
// it is stored in the instanceklass as a NULL-terminated UTF-8 string
const char* _source_debug_extension;
// Array name derived from this class which needs unreferencing
// if this class is unloaded.
Symbol* _array_name;
// Number of heapOopSize words used by non-static fields in this klass
// (including inherited fields but after header_size()).
@ -734,10 +731,6 @@ public:
const char* source_debug_extension() const { return _source_debug_extension; }
void set_source_debug_extension(const char* array, int length);
// symbol unloading support (refcount already added)
Symbol* array_name() { return _array_name; }
void set_array_name(Symbol* name) { assert(_array_name == NULL || name == NULL, "name already created"); _array_name = name; }
// nonstatic oop-map blocks
static int nonstatic_oop_map_size(unsigned int oop_map_count) {
return oop_map_count * OopMapBlock::size_in_words();
@ -1193,7 +1186,8 @@ public:
// callbacks for actions during class unloading
static void unload_class(InstanceKlass* ik);
static void release_C_heap_structures(InstanceKlass* ik);
virtual void release_C_heap_structures();
// Naming
const char* signature_name() const;
@ -1304,7 +1298,7 @@ private:
PrivateLookupMode private_mode);
// Free CHeap allocated fields.
void release_C_heap_structures();
void release_C_heap_structures_internal();
#if INCLUDE_JVMTI
// RedefineClasses support

@ -94,6 +94,10 @@ bool Klass::is_subclass_of(const Klass* k) const {
return false;
}
void Klass::release_C_heap_structures() {
if (_name != NULL) _name->decrement_refcount();
}
bool Klass::search_secondary_supers(Klass* k) const {
// Put some extra logic here out-of-line, before the search proper.
// This cuts down the size of the inline method.

@ -674,6 +674,8 @@ protected:
Symbol* name() const { return _name; }
void set_name(Symbol* n);
virtual void release_C_heap_structures();
public:
// jvm support
virtual jint compute_modifier_flags(TRAPS) const;

@ -98,9 +98,7 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
// Create type name for klass.
Symbol* name = NULL;
if (!element_klass->is_instance_klass() ||
(name = InstanceKlass::cast(element_klass)->array_name()) == NULL) {
{
ResourceMark rm(THREAD);
char *name_str = element_klass->name()->as_C_string();
int len = element_klass->name()->utf8_length();
@ -116,11 +114,7 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
new_str[idx++] = JVM_SIGNATURE_ENDCLASS;
}
new_str[idx++] = '\0';
name = SymbolTable::new_permanent_symbol(new_str);
if (element_klass->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(element_klass);
ik->set_array_name(name);
}
name = SymbolTable::new_symbol(new_str);
}
// Initialize instance variables
@ -143,12 +137,8 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
}
ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, ID) {
this->set_dimension(n);
this->set_element_klass(element_klass);
// decrement refcount because object arrays are not explicitly freed. The
// InstanceKlass array_name() keeps the name counted while the klass is
// loaded.
name->decrement_refcount();
set_dimension(n);
set_element_klass(element_klass);
Klass* bk;
if (element_klass->is_objArray_klass()) {
@ -157,12 +147,12 @@ ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayK
bk = element_klass;
}
assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass");
this->set_bottom_klass(bk);
this->set_class_loader_data(bk->class_loader_data());
set_bottom_klass(bk);
set_class_loader_data(bk->class_loader_data());
this->set_layout_helper(array_layout_helper(T_OBJECT));
assert(this->is_array_klass(), "sanity");
assert(this->is_objArray_klass(), "sanity");
set_layout_helper(array_layout_helper(T_OBJECT));
assert(is_array_klass(), "sanity");
assert(is_objArray_klass(), "sanity");
}
int ObjArrayKlass::oop_size(oop obj) const {