// for debugging and hsfind(x) bool ClassLoaderDataGraph::contains(address x) { // I think we need the _metaspace_lock taken here because the class loader // data graph could be changing while we are walking it (new entries added, // new entries being unloaded, etc). if (DumpSharedSpaces) { // There are only two metaspaces to worry about. ClassLoaderData* ncld = ClassLoaderData::the_null_class_loader_data(); return (ncld->ro_metaspace()->contains(x) || ncld->rw_metaspace()->contains(x)); } if (UseSharedSpaces && MetaspaceShared::is_in_shared_space(x)) { return true; } for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { if (cld->metaspace_or_null() != NULL && cld->metaspace_or_null()->contains(x)) { return true; } } // Could also be on an unloading list which is okay, ie. still allocated // for a little while. for (ClassLoaderData* ucld = _unloading; ucld != NULL; ucld = ucld->next()) { if (ucld->metaspace_or_null() != NULL && ucld->metaspace_or_null()->contains(x)) { return true; } } return false; }
// Move class loader data from main list to the unloaded list for unloading // and deallocation later. bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, bool clean_previous_versions) { ClassLoaderData* data = _head; ClassLoaderData* prev = NULL; bool seen_dead_loader = false; // Mark metadata seen on the stack only so we can delete unneeded entries. // Only walk all metadata, including the expensive code cache walk, for Full GC // and only if class redefinition and if there's previous versions of // Klasses to delete. bool walk_all_metadata = clean_previous_versions && JvmtiExport::has_redefined_a_class() && InstanceKlass::has_previous_versions(); MetadataOnStackMark md_on_stack(walk_all_metadata); // Save previous _unloading pointer for CMS which may add to unloading list before // purging and we don't want to rewalk the previously unloaded class loader data. _saved_unloading = _unloading; data = _head; while (data != NULL) { if (data->is_alive(is_alive_closure)) { // clean metaspace if (walk_all_metadata) { data->classes_do(InstanceKlass::purge_previous_versions); } data->free_deallocate_list(); prev = data; data = data->next(); continue; } seen_dead_loader = true; ClassLoaderData* dead = data; dead->unload(); data = data->next(); // Remove from loader list. // This class loader data will no longer be found // in the ClassLoaderDataGraph. if (prev != NULL) { prev->set_next(data); } else { assert(dead == _head, "sanity check"); _head = data; } dead->set_next(_unloading); _unloading = dead; } if (seen_dead_loader) { post_class_unload_events(); } return seen_dead_loader; }
void ClassLoaderDataGraph::keep_alive_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { if (cld->keep_alive()) { cld->oops_do(f, klass_closure, must_claim); } } }
// Move class loader data from main list to the unloaded list for unloading // and deallocation later. bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) { ClassLoaderData* data = _head; ClassLoaderData* prev = NULL; bool seen_dead_loader = false; // Save previous _unloading pointer for CMS which may add to unloading list before // purging and we don't want to rewalk the previously unloaded class loader data. _saved_unloading = _unloading; // mark metadata seen on the stack and code cache so we can delete // unneeded entries. bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); MetadataOnStackMark md_on_stack; while (data != NULL) { if (data->is_alive(is_alive_closure)) { if (has_redefined_a_class) { data->classes_do(InstanceKlass::purge_previous_versions); } data->free_deallocate_list(); prev = data; data = data->next(); continue; } seen_dead_loader = true; ClassLoaderData* dead = data; dead->unload(); data = data->next(); // Remove from loader list. // This class loader data will no longer be found // in the ClassLoaderDataGraph. if (prev != NULL) { prev->set_next(data); } else { assert(dead == _head, "sanity check"); _head = data; } dead->set_next(_unloading); _unloading = dead; } if (seen_dead_loader) { post_class_unload_events(); } return seen_dead_loader; }
void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); // Only walk the head until any clds not purged from prior unloading // (CMS doesn't purge right away). for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) { cld->classes_do(f); } }
bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) { for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { if (loader_data == data) { return true; } } return false; }
bool ClassLoaderDataGraph::unload_list_contains(const void* x) { assert(SafepointSynchronize::is_at_safepoint(), "only safe to call at safepoint"); for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) { if (cld->metaspace_or_null() != NULL && cld->metaspace_or_null()->contains(x)) { return true; } } return false; }
ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic() : _next_klass(NULL) { ClassLoaderData* cld = ClassLoaderDataGraph::_head; Klass* klass = NULL; // Find the first klass in the CLDG. while (cld != NULL) { klass = cld->_klasses; if (klass != NULL) { _next_klass = klass; return; } cld = cld->next(); } }
Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass_in_cldg(Klass* klass) { Klass* next = klass->next_link(); if (next != NULL) { return next; } // No more klasses in the current CLD. Time to find a new CLD. ClassLoaderData* cld = klass->class_loader_data(); while (next == NULL) { cld = cld->next(); if (cld == NULL) { break; } next = cld->_klasses; } return next; }
void ClassLoaderDataGraph::classes_do(void f(Klass* const)) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { cld->classes_do(f); } }
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) { for (ClassLoaderData* cld = _head; cl != NULL && cld != NULL; cld = cld->next()) { cl->do_cld(cld); } }
void ClassLoaderDataGraph::clear_claimed_marks() { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { cld->clear_claimed(); } }
void ClassLoaderDataGraph::methods_do(void f(Method*)) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { cld->methods_do(f); } }
void ClassLoaderDataGraph::verify() { for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { data->verify(); } }
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { cld->loaded_classes_do(klass_closure); } }
void ClassLoaderDataGraph::dump_on(outputStream * const out) { for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { data->dump(out); } MetaspaceAux::dump(out); }
void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) { cld->classes_do(f); } }