--- old/src/hotspot/share/classfile/classLoaderData.cpp 2018-03-26 13:40:52.933910302 -0400 +++ new/src/hotspot/share/classfile/classLoaderData.cpp 2018-03-26 13:40:52.550874915 -0400 @@ -56,6 +56,7 @@ #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" @@ -510,6 +511,12 @@ } +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) { @@ -617,24 +624,14 @@ // 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::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 alive = keep_alive() // null class loader and incomplete anonymous klasses. - || is_alive_closure->do_object_b(keep_alive_object()); +bool ClassLoaderData::is_alive() const { + bool alive = keep_alive() // null class loader and incomplete anonymous klasses. + || _holder.is_null() + || (_holder.peek() != NULL); // not cleaned by weak reference processing return alive; } @@ -668,6 +665,11 @@ 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 @@ -969,7 +971,6 @@ 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); @@ -978,8 +979,13 @@ // 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; @@ -1244,6 +1250,8 @@ 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 @@ -1260,7 +1268,7 @@ 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); @@ -1268,9 +1276,11 @@ 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(); @@ -1313,6 +1323,8 @@ 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; }