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
src/hotspot/share
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user