mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
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:
parent
05bf8dced5
commit
f8ab03fa04
6 changed files with 30 additions and 45 deletions
|
@ -640,8 +640,8 @@ public:
|
||||||
} else {
|
} else {
|
||||||
assert(k->is_instance_klass(), "Must be");
|
assert(k->is_instance_klass(), "Must be");
|
||||||
_instance_class_released ++;
|
_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()) {
|
} else if (m->is_klass()) {
|
||||||
InstanceKlass* ik = (InstanceKlass*)m;
|
InstanceKlass* ik = (InstanceKlass*)m;
|
||||||
// also releases ik->constants() C heap memory
|
// 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
|
// Remove the class so unloading events aren't triggered for
|
||||||
// this class (scratch or error class) in do_unloading().
|
// this class (scratch or error class) in do_unloading().
|
||||||
remove_class(ik);
|
remove_class(ik);
|
||||||
|
|
|
@ -587,9 +587,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
// to deallocate.
|
// to deallocate.
|
||||||
assert(array_klasses() == NULL, "array classes shouldn't be created for this class yet");
|
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.
|
// reference counting symbol names.
|
||||||
release_C_heap_structures();
|
release_C_heap_structures_internal();
|
||||||
|
|
||||||
deallocate_methods(loader_data, methods());
|
deallocate_methods(loader_data, methods());
|
||||||
set_methods(NULL);
|
set_methods(NULL);
|
||||||
|
@ -2386,7 +2386,6 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||||
it->push((Klass**)&_array_klasses);
|
it->push((Klass**)&_array_klasses);
|
||||||
it->push(&_constants);
|
it->push(&_constants);
|
||||||
it->push(&_inner_classes);
|
it->push(&_inner_classes);
|
||||||
it->push(&_array_name);
|
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
it->push(&_previous_versions);
|
it->push(&_previous_versions);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2581,17 +2580,19 @@ static void method_release_C_heap_structures(Method* m) {
|
||||||
m->release_C_heap_structures();
|
m->release_C_heap_structures();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceKlass::release_C_heap_structures(InstanceKlass* ik) {
|
void InstanceKlass::release_C_heap_structures() {
|
||||||
|
|
||||||
// Clean up C heap
|
// Clean up C heap
|
||||||
ik->release_C_heap_structures();
|
release_C_heap_structures_internal();
|
||||||
ik->constants()->release_C_heap_structures();
|
constants()->release_C_heap_structures();
|
||||||
|
|
||||||
// Deallocate and call destructors for MDO mutexes
|
// 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
|
// Can't release the constant pool here because the constant pool can be
|
||||||
// deallocated separately from the InstanceKlass for default methods and
|
// deallocated separately from the InstanceKlass for default methods and
|
||||||
// redefine classes.
|
// redefine classes.
|
||||||
|
@ -2629,12 +2630,6 @@ void InstanceKlass::release_C_heap_structures() {
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
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,
|
// 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
|
// it is stored in the instanceklass as a NULL-terminated UTF-8 string
|
||||||
const char* _source_debug_extension;
|
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
|
// Number of heapOopSize words used by non-static fields in this klass
|
||||||
// (including inherited fields but after header_size()).
|
// (including inherited fields but after header_size()).
|
||||||
|
@ -734,10 +731,6 @@ public:
|
||||||
const char* source_debug_extension() const { return _source_debug_extension; }
|
const char* source_debug_extension() const { return _source_debug_extension; }
|
||||||
void set_source_debug_extension(const char* array, int length);
|
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
|
// nonstatic oop-map blocks
|
||||||
static int nonstatic_oop_map_size(unsigned int oop_map_count) {
|
static int nonstatic_oop_map_size(unsigned int oop_map_count) {
|
||||||
return oop_map_count * OopMapBlock::size_in_words();
|
return oop_map_count * OopMapBlock::size_in_words();
|
||||||
|
@ -1193,7 +1186,8 @@ public:
|
||||||
|
|
||||||
// callbacks for actions during class unloading
|
// callbacks for actions during class unloading
|
||||||
static void unload_class(InstanceKlass* ik);
|
static void unload_class(InstanceKlass* ik);
|
||||||
static void release_C_heap_structures(InstanceKlass* ik);
|
|
||||||
|
virtual void release_C_heap_structures();
|
||||||
|
|
||||||
// Naming
|
// Naming
|
||||||
const char* signature_name() const;
|
const char* signature_name() const;
|
||||||
|
@ -1304,7 +1298,7 @@ private:
|
||||||
PrivateLookupMode private_mode);
|
PrivateLookupMode private_mode);
|
||||||
|
|
||||||
// Free CHeap allocated fields.
|
// Free CHeap allocated fields.
|
||||||
void release_C_heap_structures();
|
void release_C_heap_structures_internal();
|
||||||
|
|
||||||
#if INCLUDE_JVMTI
|
#if INCLUDE_JVMTI
|
||||||
// RedefineClasses support
|
// RedefineClasses support
|
||||||
|
|
|
@ -94,6 +94,10 @@ bool Klass::is_subclass_of(const Klass* k) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Klass::release_C_heap_structures() {
|
||||||
|
if (_name != NULL) _name->decrement_refcount();
|
||||||
|
}
|
||||||
|
|
||||||
bool Klass::search_secondary_supers(Klass* k) const {
|
bool Klass::search_secondary_supers(Klass* k) const {
|
||||||
// Put some extra logic here out-of-line, before the search proper.
|
// Put some extra logic here out-of-line, before the search proper.
|
||||||
// This cuts down the size of the inline method.
|
// This cuts down the size of the inline method.
|
||||||
|
|
|
@ -674,6 +674,8 @@ protected:
|
||||||
Symbol* name() const { return _name; }
|
Symbol* name() const { return _name; }
|
||||||
void set_name(Symbol* n);
|
void set_name(Symbol* n);
|
||||||
|
|
||||||
|
virtual void release_C_heap_structures();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// jvm support
|
// jvm support
|
||||||
virtual jint compute_modifier_flags(TRAPS) const;
|
virtual jint compute_modifier_flags(TRAPS) const;
|
||||||
|
|
|
@ -98,9 +98,7 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
|
||||||
|
|
||||||
// Create type name for klass.
|
// Create type name for klass.
|
||||||
Symbol* name = NULL;
|
Symbol* name = NULL;
|
||||||
if (!element_klass->is_instance_klass() ||
|
{
|
||||||
(name = InstanceKlass::cast(element_klass)->array_name()) == NULL) {
|
|
||||||
|
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
char *name_str = element_klass->name()->as_C_string();
|
char *name_str = element_klass->name()->as_C_string();
|
||||||
int len = element_klass->name()->utf8_length();
|
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++] = JVM_SIGNATURE_ENDCLASS;
|
||||||
}
|
}
|
||||||
new_str[idx++] = '\0';
|
new_str[idx++] = '\0';
|
||||||
name = SymbolTable::new_permanent_symbol(new_str);
|
name = SymbolTable::new_symbol(new_str);
|
||||||
if (element_klass->is_instance_klass()) {
|
|
||||||
InstanceKlass* ik = InstanceKlass::cast(element_klass);
|
|
||||||
ik->set_array_name(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize instance variables
|
// 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) {
|
ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, ID) {
|
||||||
this->set_dimension(n);
|
set_dimension(n);
|
||||||
this->set_element_klass(element_klass);
|
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();
|
|
||||||
|
|
||||||
Klass* bk;
|
Klass* bk;
|
||||||
if (element_klass->is_objArray_klass()) {
|
if (element_klass->is_objArray_klass()) {
|
||||||
|
@ -157,12 +147,12 @@ ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayK
|
||||||
bk = element_klass;
|
bk = element_klass;
|
||||||
}
|
}
|
||||||
assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass");
|
assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass");
|
||||||
this->set_bottom_klass(bk);
|
set_bottom_klass(bk);
|
||||||
this->set_class_loader_data(bk->class_loader_data());
|
set_class_loader_data(bk->class_loader_data());
|
||||||
|
|
||||||
this->set_layout_helper(array_layout_helper(T_OBJECT));
|
set_layout_helper(array_layout_helper(T_OBJECT));
|
||||||
assert(this->is_array_klass(), "sanity");
|
assert(is_array_klass(), "sanity");
|
||||||
assert(this->is_objArray_klass(), "sanity");
|
assert(is_objArray_klass(), "sanity");
|
||||||
}
|
}
|
||||||
|
|
||||||
int ObjArrayKlass::oop_size(oop obj) const {
|
int ObjArrayKlass::oop_size(oop obj) const {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue