bool Dictionary::do_unloading() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); bool class_was_unloaded = false; int index = 0; // Defined here for portability! Do not move // Remove unloadable entries and classes from system dictionary // The placeholder array has been handled in always_strong_oops_do. DictionaryEntry* probe = NULL; for (index = 0; index < table_size(); index++) { for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) { probe = *p; Klass* e = probe->klass(); ClassLoaderData* loader_data = probe->loader_data(); InstanceKlass* ik = InstanceKlass::cast(e); // Non-unloadable classes were handled in always_strong_oops_do if (!is_strongly_reachable(loader_data, e)) { // Entry was not visited in phase1 (negated test from phase1) assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader"); ClassLoaderData* k_def_class_loader_data = ik->class_loader_data(); // Do we need to delete this system dictionary entry? bool purge_entry = false; // Do we need to delete this system dictionary entry? if (loader_data->is_unloading()) { // If the loader is not live this entry should always be // removed (will never be looked up again). Note that this is // not the same as unloading the referred class. if (k_def_class_loader_data == loader_data) { // This is the defining entry, so the referred class is about // to be unloaded. class_was_unloaded = true; } // Also remove this system dictionary entry. purge_entry = true; } else { // The loader in this entry is alive. If the klass is dead, // (determined by checking the defining class loader) // the loader must be an initiating loader (rather than the // defining loader). Remove this entry. if (k_def_class_loader_data->is_unloading()) { // If we get here, the class_loader_data must not be the defining // loader, it must be an initiating one. assert(k_def_class_loader_data != loader_data, "cannot have live defining loader and unreachable klass"); // Loader is live, but class and its defining loader are dead. // Remove the entry. The class is going away. purge_entry = true; } } if (purge_entry) { *p = probe->next(); if (probe == _current_class_entry) { _current_class_entry = NULL; } free_entry(probe); continue; } } p = probe->next_addr(); } } return class_was_unloaded; }