< prev index next >

src/hotspot/share/classfile/classLoaderData.cpp

Print this page

        

*** 45,56 **** // // The bootstrap loader (represented by NULL) also has a ClassLoaderData, // the singleton class the_null_class_loader_data(). #include "precompiled.hpp" - #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/dictionary.hpp" #include "classfile/javaClasses.hpp" #include "classfile/metadataOnStackMark.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/packageEntry.hpp" --- 45,56 ---- // // The bootstrap loader (represented by NULL) also has a ClassLoaderData, // the singleton class the_null_class_loader_data(). #include "precompiled.hpp" #include "classfile/classLoaderData.inline.hpp" + #include "classfile/classLoaderDataGraph.inline.hpp" #include "classfile/dictionary.hpp" #include "classfile/javaClasses.hpp" #include "classfile/metadataOnStackMark.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/packageEntry.hpp"
*** 60,87 **** #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" - #include "memory/universe.hpp" #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" #include "oops/weakHandle.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutex.hpp" #include "runtime/orderAccess.hpp" #include "runtime/safepoint.hpp" - #include "runtime/safepointVerifiers.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" - volatile size_t ClassLoaderDataGraph::_num_array_classes = 0; - volatile size_t ClassLoaderDataGraph::_num_instance_classes = 0; - ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL; void ClassLoaderData::init_null_class_loader_data() { assert(_the_null_class_loader_data == NULL, "cannot initialize twice"); assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice"); --- 60,82 ----
*** 442,458 **** // Added a potentially young gen oop to the ClassLoaderData record_modified_oops(); } } - - void ClassLoaderDataGraph::clear_claimed_marks() { - for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { - cld->clear_claimed(); - } - } - void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) { { MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); Klass* old_value = _klasses; k->set_next_link(old_value); --- 437,446 ----
*** 476,557 **** ls.cr(); } } } - // Class iterator used by the compiler. It gets some number of classes at - // a safepoint to decay invocation counters on the methods. - class ClassLoaderDataGraphKlassIteratorStatic { - ClassLoaderData* _current_loader_data; - Klass* _current_class_entry; - public: - - ClassLoaderDataGraphKlassIteratorStatic() : _current_loader_data(NULL), _current_class_entry(NULL) {} - - InstanceKlass* try_get_next_class() { - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); - size_t max_classes = ClassLoaderDataGraph::num_instance_classes(); - assert(max_classes > 0, "should not be called with no instance classes"); - for (size_t i = 0; i < max_classes; ) { - - if (_current_class_entry != NULL) { - Klass* k = _current_class_entry; - _current_class_entry = _current_class_entry->next_link(); - - if (k->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(k); - i++; // count all instance classes found - // Not yet loaded classes are counted in max_classes - // but only return loaded classes. - if (ik->is_loaded()) { - return ik; - } - } - } else { - // Go to next CLD - if (_current_loader_data != NULL) { - _current_loader_data = _current_loader_data->next(); - } - // Start at the beginning - if (_current_loader_data == NULL) { - _current_loader_data = ClassLoaderDataGraph::_head; - } - - _current_class_entry = _current_loader_data->klasses(); - } - } - // Should never be reached unless all instance classes have failed or are not fully loaded. - // Caller handles NULL. - return NULL; - } - - // If the current class for the static iterator is a class being unloaded or - // deallocated, adjust the current class. - void adjust_saved_class(ClassLoaderData* cld) { - if (_current_loader_data == cld) { - _current_loader_data = cld->next(); - if (_current_loader_data != NULL) { - _current_class_entry = _current_loader_data->klasses(); - } // else try_get_next_class will start at the head - } - } - - void adjust_saved_class(Klass* klass) { - if (_current_class_entry == klass) { - _current_class_entry = klass->next_link(); - } - } - }; - - static ClassLoaderDataGraphKlassIteratorStatic static_klass_iterator; - - InstanceKlass* ClassLoaderDataGraph::try_get_next_class() { - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); - return static_klass_iterator.try_get_next_class(); - } - - void ClassLoaderData::initialize_holder(Handle loader_or_mirror) { if (loader_or_mirror() != NULL) { assert(_holder.is_null(), "never replace holders"); _holder = WeakHandle<vm_class_loader_data>::create(loader_or_mirror); } --- 464,473 ----
*** 561,571 **** // or parsed class in the case of an error. void ClassLoaderData::remove_class(Klass* scratch_class) { assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); // Adjust global class iterator. ! static_klass_iterator.adjust_saved_class(scratch_class); Klass* prev = NULL; for (Klass* k = _klasses; k != NULL; k = k->next_link()) { if (k == scratch_class) { if (prev == NULL) { --- 477,487 ---- // or parsed class in the case of an error. void ClassLoaderData::remove_class(Klass* scratch_class) { assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); // Adjust global class iterator. ! ClassLoaderDataGraph::adjust_saved_class(scratch_class); Klass* prev = NULL; for (Klass* k = _klasses; k != NULL; k = k->next_link()) { if (k == scratch_class) { if (prev == NULL) {
*** 609,619 **** // these classes are unloading. Must be called // after erroneous classes are released. classes_do(InstanceKlass::unload_class); // Clean up global class iterator for compiler ! static_klass_iterator.adjust_saved_class(this); } ModuleEntryTable* ClassLoaderData::modules() { // Lazily create the module entry table at first request. // Lock-free access requires load_acquire. --- 525,535 ---- // these classes are unloading. Must be called // after erroneous classes are released. classes_do(InstanceKlass::unload_class); // Clean up global class iterator for compiler ! ClassLoaderDataGraph::adjust_saved_class(this); } ModuleEntryTable* ClassLoaderData::modules() { // Lazily create the module entry table at first request. // Lock-free access requires load_acquire.
*** 912,956 **** ClassLoaderDataGraph::set_should_clean_deallocate_lists(); } } } - void ClassLoaderDataGraph::clean_deallocate_lists(bool walk_previous_versions) { - assert(SafepointSynchronize::is_at_safepoint(), "must only be called at safepoint"); - uint loaders_processed = 0; - for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { - // is_alive check will be necessary for concurrent class unloading. - if (cld->is_alive()) { - // clean metaspace - if (walk_previous_versions) { - cld->classes_do(InstanceKlass::purge_previous_versions); - } - cld->free_deallocate_list(); - loaders_processed++; - } - } - log_debug(class, loader, data)("clean_deallocate_lists: loaders processed %u %s", - loaders_processed, walk_previous_versions ? "walk_previous_versions" : ""); - } - - void ClassLoaderDataGraph::walk_metadata_and_clean_metaspaces() { - assert(SafepointSynchronize::is_at_safepoint(), "must only be called at safepoint"); - - _should_clean_deallocate_lists = false; // assume everything gets cleaned - - // Mark metadata seen on the stack so we can delete unreferenced entries. - // Walk all metadata, including the expensive code cache walk, only for class redefinition. - // The MetadataOnStackMark walk during redefinition saves previous versions if it finds old methods - // on the stack or in the code cache, so we only have to repeat the full walk if - // they were found at that time. - // TODO: have redefinition clean old methods out of the code cache. They still exist in some places. - bool walk_all_metadata = InstanceKlass::has_previous_versions_and_reset(); - - MetadataOnStackMark md_on_stack(walk_all_metadata); - clean_deallocate_lists(walk_all_metadata); - } - // This is distinct from free_deallocate_list. For class loader data that are // unloading, this frees the C heap memory for items on the list, and unlinks // scratch or error classes so that unloading events aren't triggered for these // classes. The metadata is removed with the unloading metaspace. // There isn't C heap memory allocated for methods, so nothing is done for them. --- 828,837 ----
*** 1068,1592 **** for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) { if (k == klass) return true; } return false; } - - - // GC root of class loader data created. - ClassLoaderData* ClassLoaderDataGraph::_head = NULL; - ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL; - ClassLoaderData* ClassLoaderDataGraph::_saved_unloading = NULL; - ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL; - - bool ClassLoaderDataGraph::_should_purge = false; - bool ClassLoaderDataGraph::_should_clean_deallocate_lists = false; - bool ClassLoaderDataGraph::_safepoint_cleanup_needed = false; - bool ClassLoaderDataGraph::_metaspace_oom = false; - - // Add a new class loader data node to the list. Assign the newly created - // ClassLoaderData into the java/lang/ClassLoader object as a hidden field - ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_unsafe_anonymous) { - - assert_lock_strong(ClassLoaderDataGraph_lock); - - ClassLoaderData* cld; - - // First check if another thread beat us to creating the CLD and installing - // it into the loader while we were waiting for the lock. - if (!is_unsafe_anonymous && loader.not_null()) { - cld = java_lang_ClassLoader::loader_data_acquire(loader()); - if (cld != NULL) { - return cld; - } - } - - // We mustn't GC until we've installed the ClassLoaderData in the Graph since the CLD - // contains oops in _handles that must be walked. GC doesn't walk CLD from the - // loader oop in all collections, particularly young collections. - NoSafepointVerifier no_safepoints; - - cld = new ClassLoaderData(loader, is_unsafe_anonymous); - - // First install the new CLD to the Graph. - cld->set_next(_head); - _head = cld; - - // Next associate with the class_loader. - if (!is_unsafe_anonymous) { - // Use OrderAccess, since readers need to get the loader_data only after - // it's added to the Graph - java_lang_ClassLoader::release_set_loader_data(loader(), cld); - } - - // Lastly log, if requested - LogTarget(Trace, class, loader, data) lt; - if (lt.is_enabled()) { - ResourceMark rm; - LogStream ls(lt); - ls.print("create "); - cld->print_value_on(&ls); - ls.cr(); - } - return cld; - } - - ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_unsafe_anonymous) { - MutexLocker ml(ClassLoaderDataGraph_lock); - ClassLoaderData* loader_data = add_to_graph(loader, is_unsafe_anonymous); - return loader_data; - } - - void ClassLoaderDataGraph::cld_do(CLDClosure* cl) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) { - cl->do_cld(cld); - } - } - - void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - // 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()) { - assert(cld->is_unloading(), "invariant"); - cl->do_cld(cld); - } - } - - void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->_next) { - CLDClosure* closure = cld->keep_alive() ? strong : weak; - if (closure != NULL) { - closure->do_cld(cld); - } - } - } - - void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - if (ClassUnloading) { - roots_cld_do(cl, NULL); - } else { - cld_do(cl); - } - } - - // Closure for locking and iterating through classes. - LockedClassesDo::LockedClassesDo(classes_do_func_t f) : _function(f) { - ClassLoaderDataGraph_lock->lock(); - } - - LockedClassesDo::LockedClassesDo() : _function(NULL) { - // callers provide their own do_klass - ClassLoaderDataGraph_lock->lock(); - } - - LockedClassesDo::~LockedClassesDo() { ClassLoaderDataGraph_lock->unlock(); } - - - // Iterating over the CLDG needs to be locked because - // unloading can remove entries concurrently soon. - class ClassLoaderDataGraphIterator : public StackObj { - ClassLoaderData* _next; - HandleMark _hm; // clean up handles when this is done. - Handle _holder; - Thread* _thread; - - void hold_next() { - if (_next != NULL) { - _holder = Handle(_thread, _next->holder_phantom()); - } - } - public: - ClassLoaderDataGraphIterator() : _next(ClassLoaderDataGraph::_head) { - _thread = Thread::current(); - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - hold_next(); - } - - bool repeat() const { - return _next != NULL; - } - - ClassLoaderData* get_next() { - ClassLoaderData* next = _next; - if (_next != NULL) { - _next = _next->next(); - hold_next(); - } - return next; - } - }; - - // These functions assume that the caller has locked the ClassLoaderDataGraph_lock - // if they are not calling the function from a safepoint. - void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) { - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->classes_do(klass_closure); - } - } - - void ClassLoaderDataGraph::classes_do(void f(Klass* const)) { - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->classes_do(f); - } - } - - void ClassLoaderDataGraph::methods_do(void f(Method*)) { - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->methods_do(f); - } - } - - void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) { - assert_locked_or_safepoint(Module_lock); - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->modules_do(f); - } - } - - void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - // 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()) { - assert(cld->is_unloading(), "invariant"); - cld->modules_do(f); - } - } - - void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) { - assert_locked_or_safepoint(Module_lock); - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->packages_do(f); - } - } - - void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - // 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()) { - assert(cld->is_unloading(), "invariant"); - cld->packages_do(f); - } - } - - void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) { - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->loaded_classes_do(klass_closure); - } - } - - // This case can block but cannot do unloading (called from CDS) - void ClassLoaderDataGraph::unlocked_loaded_classes_do(KlassClosure* klass_closure) { - for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { - cld->loaded_classes_do(klass_closure); - } - } - - - void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - // 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()) { - assert(cld->is_unloading(), "invariant"); - cld->classes_do(f); - } - } - - #define FOR_ALL_DICTIONARY(X) ClassLoaderDataGraphIterator iter; \ - ClassLoaderData* X; \ - while ((X = iter.get_next()) != NULL) \ - if (X->dictionary() != NULL) - - // Walk classes in the loaded class dictionaries in various forms. - // Only walks the classes defined in this class loader. - void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) { - FOR_ALL_DICTIONARY(cld) { - cld->dictionary()->classes_do(f); - } - } - - // Only walks the classes defined in this class loader. - void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) { - FOR_ALL_DICTIONARY(cld) { - cld->dictionary()->classes_do(f, CHECK); - } - } - - void ClassLoaderDataGraph::verify_dictionary() { - FOR_ALL_DICTIONARY(cld) { - cld->dictionary()->verify(); - } - } - - void ClassLoaderDataGraph::print_dictionary(outputStream* st) { - FOR_ALL_DICTIONARY(cld) { - st->print("Dictionary for "); - cld->print_value_on(st); - st->cr(); - cld->dictionary()->print_on(st); - st->cr(); - } - } - - void ClassLoaderDataGraph::print_dictionary_statistics(outputStream* st) { - FOR_ALL_DICTIONARY(cld) { - ResourceMark rm; - stringStream tempst; - tempst.print("System Dictionary for %s class loader", cld->loader_name_and_id()); - cld->dictionary()->print_table_statistics(st, tempst.as_string()); - } - } - - GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?"); - - GrowableArray<ClassLoaderData*>* array = new GrowableArray<ClassLoaderData*>(); - - // The CLDs in [_head, _saved_head] were all added during last call to remember_new_clds(true); - ClassLoaderData* curr = _head; - while (curr != _saved_head) { - if (!curr->claimed()) { - array->push(curr); - LogTarget(Debug, class, loader, data) lt; - if (lt.is_enabled()) { - LogStream ls(lt); - ls.print("found new CLD: "); - curr->print_value_on(&ls); - ls.cr(); - } - } - - curr = curr->_next; - } - - return array; - } - - #ifndef PRODUCT - bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - for (ClassLoaderData* data = _head; data != NULL; data = data->next()) { - if (loader_data == data) { - return true; - } - } - - return false; - } - #endif // PRODUCT - - // Move class loader data from main list to the unloaded list for unloading - // and deallocation later. - bool ClassLoaderDataGraph::do_unloading(bool do_cleaning) { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - - // Indicate whether safepoint cleanup is needed. - _safepoint_cleanup_needed |= do_cleaning; - - ClassLoaderData* data = _head; - ClassLoaderData* prev = NULL; - bool seen_dead_loader = false; - uint loaders_processed = 0; - uint loaders_removed = 0; - - // 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()) { - prev = data; - data = data->next(); - loaders_processed++; - continue; - } - seen_dead_loader = true; - loaders_removed++; - 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; - } - - log_debug(class, loader, data)("do_unloading: loaders processed %u, loaders removed %u", loaders_processed, loaders_removed); - - return seen_dead_loader; - } - - // There's at least one dead class loader. Purge refererences of healthy module - // reads lists and package export lists to modules belonging to dead loaders. - void ClassLoaderDataGraph::clean_module_and_package_info() { - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - - ClassLoaderData* data = _head; - while (data != NULL) { - // Remove entries in the dictionary of live class loader that have - // initiated loading classes in a dead class loader. - if (data->dictionary() != NULL) { - data->dictionary()->do_unloading(); - } - // Walk a ModuleEntry's reads, and a PackageEntry's exports - // lists to determine if there are modules on those lists that are now - // dead and should be removed. A module's life cycle is equivalent - // to its defining class loader's life cycle. Since a module is - // considered dead if its class loader is dead, these walks must - // occur after each class loader's aliveness is determined. - if (data->packages() != NULL) { - data->packages()->purge_all_package_exports(); - } - if (data->modules_defined()) { - data->modules()->purge_all_module_reads(); - } - data = data->next(); - } - } - - void ClassLoaderDataGraph::purge() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); - ClassLoaderData* list = _unloading; - _unloading = NULL; - ClassLoaderData* next = list; - bool classes_unloaded = false; - while (next != NULL) { - ClassLoaderData* purge_me = next; - next = purge_me->next(); - delete purge_me; - classes_unloaded = true; - } - if (classes_unloaded) { - Metaspace::purge(); - set_metaspace_oom(false); - } - } - - int ClassLoaderDataGraph::resize_if_needed() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); - int resized = 0; - if (Dictionary::does_any_dictionary_needs_resizing()) { - FOR_ALL_DICTIONARY(cld) { - if (cld->dictionary()->resize_if_needed()) { - resized++; - } - } - } - return resized; - } - - ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic() - : _next_klass(NULL) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); - ClassLoaderData* cld = ClassLoaderDataGraph::_head; - Klass* klass = NULL; - - // Find the first klass in the CLDG. - while (cld != NULL) { - assert_locked_or_safepoint(cld->metaspace_lock()); - 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(); - assert_locked_or_safepoint(cld->metaspace_lock()); - while (next == NULL) { - cld = cld->next(); - if (cld == NULL) { - break; - } - next = cld->_klasses; - } - - return next; - } - - Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() { - Klass* head = _next_klass; - - while (head != NULL) { - Klass* next = next_klass_in_cldg(head); - - Klass* old_head = Atomic::cmpxchg(next, &_next_klass, head); - - if (old_head == head) { - return head; // Won the CAS. - } - - head = old_head; - } - - // Nothing more for the iterator to hand out. - assert(head == NULL, "head is " PTR_FORMAT ", expected not null:", p2i(head)); - return NULL; - } - - ClassLoaderDataGraphMetaspaceIterator::ClassLoaderDataGraphMetaspaceIterator() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); - _data = ClassLoaderDataGraph::_head; - } - - ClassLoaderDataGraphMetaspaceIterator::~ClassLoaderDataGraphMetaspaceIterator() {} - - #ifndef PRODUCT - // callable from debugger - extern "C" int print_loader_data_graph() { - ResourceMark rm; - ClassLoaderDataGraph::print_on(tty); - return 0; - } - - void ClassLoaderDataGraph::verify() { - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->verify(); - } - } - - void ClassLoaderDataGraph::print_on(outputStream * const out) { - ClassLoaderDataGraphIterator iter; - while (iter.repeat()) { - ClassLoaderData* cld = iter.get_next(); - cld->print_on(out); - } - } - #endif // PRODUCT --- 949,953 ----
< prev index next >