# HG changeset patch # User coleenp # Date 1523369202 14400 # Node ID a7bc87a63dd8ec2e6fa80f70f95ca0f9830d948b # Parent 01960eec4570066fdc3e19f220f4b79a8acec7b2 8198313: Wrap holder object for ClassLoaderData in a WeakHandle Summary: Use WeakHandle for ClassLoaderData::_holder so that is_alive closure is not needed Reviewed-by: rehn, kbarrett diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/ci/ciInstanceKlass.cpp --- a/src/hotspot/share/ci/ciInstanceKlass.cpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/ci/ciInstanceKlass.cpp Tue Apr 10 10:06:42 2018 -0400 @@ -72,7 +72,7 @@ // by the GC but need to be strong roots if reachable from a current compilation. // InstanceKlass are created for both weak and strong metadata. Ensuring this metadata // alive covers the cases where there are weak roots without performance cost. - oop holder = ik->klass_holder_phantom(); + oop holder = ik->holder_phantom(); if (ik->is_anonymous()) { // Though ciInstanceKlass records class loader oop, it's not enough to keep // VM anonymous classes alive (loader == NULL). Klass holder should be used instead. diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/classfile/classLoaderData.cpp --- a/src/hotspot/share/classfile/classLoaderData.cpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/classfile/classLoaderData.cpp Tue Apr 10 10:06:42 2018 -0400 @@ -55,26 +55,22 @@ #include "classfile/moduleEntry.hpp" #include "classfile/packageEntry.hpp" #include "classfile/systemDictionary.hpp" -#include "code/codeCache.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" -#include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" +#include "memory/universe.hpp" #include "oops/access.inline.hpp" -#include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/weakHandle.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/javaCalls.hpp" -#include "runtime/jniHandles.hpp" #include "runtime/mutex.hpp" #include "runtime/orderAccess.hpp" #include "runtime/safepoint.hpp" #include "runtime/safepointVerifiers.hpp" -#include "runtime/synchronizer.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" @@ -113,17 +109,21 @@ // The null-class-loader should always be kept alive. _keep_alive((is_anonymous || h_class_loader.is_null()) ? 1 : 0), _metaspace(NULL), _unloading(false), _klasses(NULL), - _modules(NULL), _packages(NULL), + _modules(NULL), _packages(NULL), _unnamed_module(NULL), _dictionary(NULL), _claimed(0), _modified_oops(true), _accumulated_modified_oops(false), _jmethod_ids(NULL), _handles(), _deallocate_list(NULL), _next(NULL), _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, Monitor::_safepoint_check_never)) { - // A ClassLoaderData created solely for an anonymous class should never have a - // ModuleEntryTable or PackageEntryTable created for it. The defining package - // and module for an anonymous class will be found in its host class. if (!is_anonymous) { + // The holder is initialized later for anonymous classes, and before calling anything + // that call class_loader(). + initialize_holder(h_class_loader); + + // A ClassLoaderData created solely for an anonymous class should never have a + // ModuleEntryTable or PackageEntryTable created for it. The defining package + // and module for an anonymous class will be found in its host class. _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); if (h_class_loader.is_null()) { // Create unnamed module for boot loader @@ -133,10 +133,6 @@ _unnamed_module = ModuleEntry::create_unnamed_module(this); } _dictionary = create_dictionary(); - } else { - _packages = NULL; - _unnamed_module = NULL; - _dictionary = NULL; } NOT_PRODUCT(_dependency_count = 0); // number of class loader dependencies @@ -510,6 +506,13 @@ } +void ClassLoaderData::initialize_holder(Handle loader_or_mirror) { + if (loader_or_mirror() != NULL) { + assert(_holder.is_null(), "never replace holders"); + _holder = WeakHandle::create(loader_or_mirror); + } +} + // 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) { @@ -611,30 +614,23 @@ } // Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph -oop ClassLoaderData::holder_phantom() { +oop ClassLoaderData::holder_phantom() const { // 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::oop_load(o); + if (!_holder.is_null()) { // NULL class_loader + return _holder.resolve(); } else { return NULL; } } // 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.peek() != NULL); // not cleaned by weak reference processing return alive; } @@ -668,6 +664,9 @@ ClassLoaderDataGraph::dec_array_classes(cl.array_class_released()); ClassLoaderDataGraph::dec_instance_classes(cl.instance_class_released()); + // Release the WeakHandle + _holder.release(); + // Release C heap allocated hashtable for all the packages. if (_packages != NULL) { // Destroy the table itself @@ -969,7 +968,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); @@ -1244,6 +1242,8 @@ ClassLoaderData* data = _head; ClassLoaderData* prev = NULL; bool seen_dead_loader = false; + uint loaders_processed = 0; + uint 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 +1260,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 +1268,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 +1315,8 @@ post_class_unload_events(); } + log_debug(class, loader, data)("do_unloading: loaders processed %u, loaders removed %u", loaders_processed, loaders_removed); + return seen_dead_loader; } diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/classfile/classLoaderData.hpp --- a/src/hotspot/share/classfile/classLoaderData.hpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/classfile/classLoaderData.hpp Tue Apr 10 10:06:42 2018 -0400 @@ -30,6 +30,7 @@ #include "memory/metaspace.hpp" #include "memory/metaspaceCounters.hpp" #include "oops/oopHandle.hpp" +#include "oops/weakHandle.hpp" #include "runtime/mutex.hpp" #include "trace/traceMacros.hpp" #include "utilities/growableArray.hpp" @@ -113,7 +114,7 @@ static void packages_unloading_do(void f(PackageEntry*)); static void loaded_classes_do(KlassClosure* klass_closure); static void classes_unloading_do(void f(Klass* const)); - static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions); + static bool do_unloading(BoolObjectClosure* is_alive_closure, bool clean_previous_versions); // dictionary do // Iterate over all klasses in dictionary, but @@ -219,8 +220,9 @@ static ClassLoaderData * _the_null_class_loader_data; - oop _class_loader; // oop used to uniquely identify a class loader - // class loader or a canonical class path + WeakHandle _holder; // The oop that determines lifetime of this class loader + oop _class_loader; // The instance of java/lang/ClassLoader associated with + // this ClassLoaderData ClassLoaderMetaspace * volatile _metaspace; // Meta-space where meta-data defined by the // classes in the class loader are allocated. @@ -286,7 +288,8 @@ void unload(); bool keep_alive() const { return _keep_alive > 0; } - oop holder_phantom(); + + oop holder_phantom() const; void classes_do(void f(Klass*)); void loaded_classes_do(KlassClosure* klass_closure); void classes_do(void f(InstanceKlass*)); @@ -308,7 +311,7 @@ bool claimed() const { return _claimed == 1; } bool claim(); - bool is_alive(BoolObjectClosure* is_alive_closure) const; + bool is_alive() const; // Accessors ClassLoaderMetaspace* metaspace_or_null() const { return _metaspace; } @@ -348,7 +351,7 @@ // method will allocate a Metaspace if needed. ClassLoaderMetaspace* metaspace_non_null(); - oop class_loader() const { return _class_loader; } + oop class_loader() const { return _class_loader; } // The object the GC is using to keep this ClassLoaderData alive. oop keep_alive_object() const; @@ -364,6 +367,8 @@ void inc_keep_alive(); void dec_keep_alive(); + void initialize_holder(Handle holder); + inline unsigned int identity_hash() const { return (unsigned int)(((intptr_t)this) >> 3); } void oops_do(OopClosure* f, bool must_claim, bool clear_modified_oops = false); diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/classfile/systemDictionary.cpp --- a/src/hotspot/share/classfile/systemDictionary.cpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Tue Apr 10 10:06:42 2018 -0400 @@ -44,6 +44,7 @@ #include "code/codeCache.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/gcTraceTime.inline.hpp" +#include "gc/shared/oopStorage.inline.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" #include "logging/log.hpp" @@ -117,6 +118,8 @@ const int defaultProtectionDomainCacheSize = 1009; +OopStorage* SystemDictionary::_vm_weak_oop_storage = NULL; + // ---------------------------------------------------------------------------- // Java-level SystemLoader and PlatformLoader @@ -1012,7 +1015,9 @@ CHECK_NULL); if (host_klass != NULL && k != NULL) { - // If it's anonymous, initialize it now, since nobody else will. + // Anonymous classes must update ClassLoaderData holder (was host_klass loader) + // so that they can be unloaded when the mirror is no longer referenced. + k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror())); { MutexLocker mu_r(Compile_lock, THREAD); @@ -1032,6 +1037,8 @@ if (cp_patches != NULL) { k->constants()->patch_resolved_references(cp_patches); } + + // If it's anonymous, initialize it now, since nobody else will. k->eager_initialize(CHECK_NULL); // notify jvmti @@ -1848,6 +1855,10 @@ GCTimer* gc_timer, bool do_cleaning) { + { + GCTraceTime(Debug, gc, phases) t("SystemDictionary WeakHandle cleaning", gc_timer); + vm_weak_oop_storage()->weak_oops_do(is_alive, &do_nothing_cl); + } bool unloading_occurred; { @@ -1896,9 +1907,11 @@ // Only the protection domain oops contain references into the heap. Iterate // over all of them. _pd_cache_table->oops_do(strong); + vm_weak_oop_storage()->oops_do(strong); } else { if (weak != NULL) { _pd_cache_table->oops_do(weak); + vm_weak_oop_storage()->oops_do(weak); } } @@ -1924,6 +1937,8 @@ invoke_method_table()->oops_do(f); ResolvedMethodTable::oops_do(f); + + vm_weak_oop_storage()->oops_do(f); } // CDS: scan and relocate all classes in the system dictionary. @@ -3105,3 +3120,15 @@ return (loader_data->class_loader() == NULL ? "" : SystemDictionary::loader_name(loader_data->class_loader())); } + +void SystemDictionary::initialize_oop_storage() { + _vm_weak_oop_storage = + new OopStorage("VM Weak Oop Handles", + VMWeakAlloc_lock, + VMWeakActive_lock); +} + +OopStorage* SystemDictionary::vm_weak_oop_storage() { + assert(_vm_weak_oop_storage != NULL, "Uninitialized"); + return _vm_weak_oop_storage; +} diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/classfile/systemDictionary.hpp --- a/src/hotspot/share/classfile/systemDictionary.hpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/classfile/systemDictionary.hpp Tue Apr 10 10:06:42 2018 -0400 @@ -84,6 +84,7 @@ class ProtectionDomainCacheTable; class ProtectionDomainCacheEntry; class GCTimer; +class OopStorage; // Certain classes are preloaded, such as java.lang.Object and java.lang.String. // They are all "well-known", in the sense that no class loader is allowed @@ -637,6 +638,9 @@ // ProtectionDomain cache static ProtectionDomainCacheTable* _pd_cache_table; + // VM weak OopStorage object. + static OopStorage* _vm_weak_oop_storage; + protected: static void validate_protection_domain(InstanceKlass* klass, Handle class_loader, @@ -689,6 +693,9 @@ return !m->is_public() && m->method_holder() == SystemDictionary::Object_klass(); } + static void initialize_oop_storage(); + static OopStorage* vm_weak_oop_storage(); + protected: static InstanceKlass* find_shared_class(Symbol* class_name); diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/memory/universe.cpp --- a/src/hotspot/share/memory/universe.cpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/memory/universe.cpp Tue Apr 10 10:06:42 2018 -0400 @@ -689,6 +689,8 @@ return status; } + SystemDictionary::initialize_oop_storage(); + Metaspace::global_initialize(); // Initialize performance counters for metaspaces diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/oops/instanceKlass.cpp --- a/src/hotspot/share/oops/instanceKlass.cpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/oops/instanceKlass.cpp Tue Apr 10 10:06:42 2018 -0400 @@ -1901,7 +1901,7 @@ } void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { - assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); + assert(class_loader_data()->is_alive(), "this klass should be live"); if (is_interface()) { if (ClassUnloading) { Klass* impl = implementor(); @@ -3407,14 +3407,8 @@ } } -oop InstanceKlass::klass_holder_phantom() { - oop* addr; - if (is_anonymous()) { - addr = _java_mirror.ptr_raw(); - } else { - addr = &class_loader_data()->_class_loader; - } - return RootAccess::oop_load(addr); +oop InstanceKlass::holder_phantom() const { + return class_loader_data()->holder_phantom(); } #ifdef ASSERT diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/oops/instanceKlass.hpp --- a/src/hotspot/share/oops/instanceKlass.hpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/oops/instanceKlass.hpp Tue Apr 10 10:06:42 2018 -0400 @@ -646,10 +646,10 @@ return is_anonymous() ? java_mirror() : class_loader(); } - // Load the klass_holder as a phantom. This is useful when a weak Klass + // Load the klass's holder as a phantom. This is useful when a weak Klass // pointer has been "peeked" and then must be kept alive before it may // be used safely. - oop klass_holder_phantom(); + oop holder_phantom() const; bool is_contended() const { return (_misc_flags & _misc_is_contended) != 0; diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/oops/weakHandle.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/oops/weakHandle.cpp Tue Apr 10 10:06:42 2018 -0400 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "classfile/systemDictionary.hpp" +#include "gc/shared/oopStorage.hpp" +#include "oops/access.inline.hpp" +#include "oops/oop.hpp" +#include "oops/weakHandle.inline.hpp" +#include "utilities/debug.hpp" +#include "utilities/ostream.hpp" + +template <> OopStorage* WeakHandle::get_storage() { + return SystemDictionary::vm_weak_oop_storage(); +} + +template +WeakHandle WeakHandle::create(Handle obj) { + assert(obj() != NULL, "no need to create weak null oop"); + oop* oop_addr = get_storage()->allocate(); + if (oop_addr == NULL) { + vm_exit_out_of_memory(sizeof(oop*), OOM_MALLOC_ERROR, "Unable to create new weak oop handle in OopStorage"); + } + // Create WeakHandle with address returned and store oop into it. + RootAccess::oop_store(oop_addr, obj()); + return WeakHandle(oop_addr); +} + +template +void WeakHandle::release() const { + // Only release if the pointer to the object has been created. + if (_obj != NULL) { + // Clear the WeakHandle. For class loader data race, the handle may not have + // been previously cleared by GC. + RootAccess::oop_store(_obj, (oop)NULL); + get_storage()->release(_obj); + } +} + +template +void WeakHandle::print() const { print_on(tty); } + +template +void WeakHandle::print_on(outputStream* st) const { + st->print("WeakHandle: " PTR_FORMAT, p2i(peek())); +} + +// Provide instantiation. +template class WeakHandle; + diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/oops/weakHandle.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/oops/weakHandle.hpp Tue Apr 10 10:06:42 2018 -0400 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OOPS_WEAKHANDLE_HPP +#define SHARE_VM_OOPS_WEAKHANDLE_HPP + +#include "oops/oop.hpp" +#include "runtime/handles.hpp" + +class outputStream; +class OopStorage; + +// A WeakHandle is a pointer to an oop that is stored in an OopStorage that is +// processed weakly by GC. The runtime structures that point to the oop must +// either peek or resolve the oop, the latter will keep the oop alive for +// the GC cycle. The runtime structures that reference the oop must test +// if the value is NULL. If it is NULL, it has been cleaned out by GC. +// This is the vm version of jweak but has different GC lifetimes and policies, +// depending on the type. + +enum WeakHandleType { vm_class_loader_data, vm_string }; + +template +class WeakHandle { + public: + + private: + oop* _obj; + + WeakHandle(oop* w) : _obj(w) {} + static OopStorage* get_storage(); + public: + WeakHandle() : _obj(NULL) {} // needed for init + + static WeakHandle create(Handle obj); + inline oop resolve() const; + inline oop peek() const; + void release() const; + bool is_null() const { return _obj == NULL; } + + void print() const; + void print_on(outputStream* st) const; +}; + +#endif // SHARE_VM_OOPS_WEAKHANDLE_HPP diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/oops/weakHandle.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/oops/weakHandle.inline.hpp Tue Apr 10 10:06:42 2018 -0400 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP +#define SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP + +#include "oops/weakHandle.hpp" +#include "oops/access.inline.hpp" + +template +oop WeakHandle::resolve() const { + assert(!is_null(), "Must be created"); + return RootAccess::oop_load(_obj); +} + +template +oop WeakHandle::peek() const { + assert(!is_null(), "Must be created"); + return RootAccess::oop_load(_obj); +} + +#endif // SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/runtime/mutexLocker.cpp --- a/src/hotspot/share/runtime/mutexLocker.cpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/runtime/mutexLocker.cpp Tue Apr 10 10:06:42 2018 -0400 @@ -48,6 +48,8 @@ Mutex* JNIWeakAlloc_lock = NULL; Mutex* JNIWeakActive_lock = NULL; Mutex* JNIHandleBlockFreeList_lock = NULL; +Mutex* VMWeakAlloc_lock = NULL; +Mutex* VMWeakActive_lock = NULL; Mutex* ResolvedMethodTable_lock = NULL; Mutex* JmethodIdCreation_lock = NULL; Mutex* JfieldIdCreation_lock = NULL; @@ -260,6 +262,8 @@ def(JNIGlobalActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never); def(JNIWeakAlloc_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never); def(JNIWeakActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never); + def(VMWeakAlloc_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never); + def(VMWeakActive_lock , PaddedMutex , nonleaf-1, true, Monitor::_safepoint_check_never); def(JNICritical_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always); // used for JNI critical regions def(AdapterHandlerLibrary_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_always); diff -r 01960eec4570 -r a7bc87a63dd8 src/hotspot/share/runtime/mutexLocker.hpp --- a/src/hotspot/share/runtime/mutexLocker.hpp Tue Apr 10 08:15:40 2018 -0400 +++ b/src/hotspot/share/runtime/mutexLocker.hpp Tue Apr 10 10:06:42 2018 -0400 @@ -41,6 +41,8 @@ extern Mutex* JNIWeakAlloc_lock; // JNI weak storage allocate list lock extern Mutex* JNIWeakActive_lock; // JNI weak storage active list lock extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list +extern Mutex* VMWeakAlloc_lock; // VM Weak Handles storage allocate list lock +extern Mutex* VMWeakActive_lock; // VM Weak Handles storage active list lock extern Mutex* ResolvedMethodTable_lock; // a lock on the ResolvedMethodTable updates extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers