< prev index next >
src/hotspot/share/classfile/classLoaderData.cpp
Print this page
@@ -54,10 +54,11 @@
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
+#include "gc/shared/oopStorage.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
@@ -508,10 +509,16 @@
InstanceKlass* ClassLoaderDataGraph::try_get_next_class() {
return static_klass_iterator.try_get_next_class();
}
+void ClassLoaderData::update_holder(Handle holder) {
+ assert(holder() != NULL, "should be called with non-NULL loader");
+ assert(_holder.peek() == NULL, "never replace holders");
+ _holder = WeakHandle::create(holder);
+}
+
// Remove a klass from the _klasses list for scratch_class during redefinition
// 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");
@@ -615,28 +622,18 @@
// A klass that was previously considered dead can be looked up in the
// CLD/SD, and its _java_mirror or _class_loader can be stored in a root
// or a reachable object making it alive again. The SATB part of G1 needs
// to get notified about this potential resurrection, otherwise the marking
// might not find the object.
- if (!keep_alive()) {
- oop* o = is_anonymous() ? _klasses->java_mirror_handle().ptr_raw() : &_class_loader;
- return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(o);
- } else {
- return NULL;
- }
+ return _holder.resolve();
}
// Unloading support
-oop ClassLoaderData::keep_alive_object() const {
- assert_locked_or_safepoint(_metaspace_lock);
- assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
- return is_anonymous() ? _klasses->java_mirror() : class_loader();
-}
-
-bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const {
+bool ClassLoaderData::is_alive() const {
bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
- || is_alive_closure->do_object_b(keep_alive_object());
+ || _holder.is_null()
+ || (_holder.peek() != NULL); // not cleaned by weak reference processing
return alive;
}
class ReleaseKlassClosure: public KlassClosure {
@@ -666,10 +663,15 @@
classes_do(&cl);
ClassLoaderDataGraph::dec_array_classes(cl.array_class_released());
ClassLoaderDataGraph::dec_instance_classes(cl.instance_class_released());
+ // Release the WeakHandle, if already set
+ if (!_holder.is_null()) {
+ _holder.release();
+ }
+
// Release C heap allocated hashtable for all the packages.
if (_packages != NULL) {
// Destroy the table itself
delete _packages;
_packages = NULL;
@@ -967,21 +969,25 @@
// ClassLoaderData in the graph since the CLD
// contains unhandled oops
ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous);
-
if (!is_anonymous) {
// First, Atomically set it
ClassLoaderData* old = java_lang_ClassLoader::cmpxchg_loader_data(cld, loader(), NULL);
if (old != NULL) {
delete cld;
// Returns the data.
return old;
}
+
+ // Update the holder if we've won the race
+ // The holder of this class is the class_loader generically.
+ cld->update_holder(loader);
}
+
// We won the race, and therefore the task of adding the data to the list of
// class loader data
ClassLoaderData** list_head = &_head;
ClassLoaderData* next = _head;
@@ -1242,10 +1248,12 @@
bool clean_previous_versions) {
ClassLoaderData* data = _head;
ClassLoaderData* prev = NULL;
bool seen_dead_loader = false;
+ int loaders_processed = 0;
+ int loaders_removed = 0;
// 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.
@@ -1258,21 +1266,23 @@
// 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)) {
+ if (data->is_alive()) {
// clean metaspace
if (walk_all_metadata) {
data->classes_do(InstanceKlass::purge_previous_versions);
}
data->free_deallocate_list();
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
@@ -1311,10 +1321,12 @@
}
post_class_unload_events();
}
+ log_debug(class, loader, data)("do_unloading: loaders processed %d, loaders removed %d", loaders_processed, loaders_removed);
+
return seen_dead_loader;
}
void ClassLoaderDataGraph::purge() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
< prev index next >