8259242: Remove ProtectionDomainSet_lock

Reviewed-by: dholmes, pchilanomate
This commit is contained in:
Coleen Phillimore 2021-04-09 14:59:43 +00:00
parent 9bb1863ed7
commit 06e6b1f7ae
10 changed files with 129 additions and 82 deletions

View file

@ -44,6 +44,7 @@
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp" #include "runtime/mutexLocker.hpp"
#include "runtime/safepointVerifiers.hpp" #include "runtime/safepointVerifiers.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp" #include "utilities/hashtable.inline.hpp"
// Optimization: if any dictionary needs resizing, we set this flag, // Optimization: if any dictionary needs resizing, we set this flag,
@ -78,20 +79,19 @@ Dictionary::~Dictionary() {
DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass) { DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass) {
DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::new_entry(hash, klass); DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::new_entry(hash, klass);
entry->set_pd_set(NULL); entry->release_set_pd_set(NULL);
assert(klass->is_instance_klass(), "Must be"); assert(klass->is_instance_klass(), "Must be");
return entry; return entry;
} }
void Dictionary::free_entry(DictionaryEntry* entry) { void Dictionary::free_entry(DictionaryEntry* entry) {
// avoid recursion when deleting linked list // avoid recursion when deleting linked list
// pd_set is accessed during a safepoint. // pd_set is accessed during a safepoint.
// This doesn't require a lock because nothing is reading this // This doesn't require a lock because nothing is reading this
// entry anymore. The ClassLoader is dead. // entry anymore. The ClassLoader is dead.
while (entry->pd_set() != NULL) { while (entry->pd_set_acquire() != NULL) {
ProtectionDomainEntry* to_delete = entry->pd_set(); ProtectionDomainEntry* to_delete = entry->pd_set_acquire();
entry->set_pd_set(to_delete->next()); entry->release_set_pd_set(to_delete->next_acquire());
delete to_delete; delete to_delete;
} }
BasicHashtable<mtClass>::free_entry(entry); BasicHashtable<mtClass>::free_entry(entry);
@ -141,15 +141,26 @@ bool DictionaryEntry::is_valid_protection_domain(Handle protection_domain) {
: contains_protection_domain(protection_domain()); : contains_protection_domain(protection_domain());
} }
// Reading the pd_set on each DictionaryEntry is lock free and cannot safepoint.
// Adding and deleting entries is under the SystemDictionary_lock
// Deleting unloaded entries on ClassLoaderData for dictionaries that are not unloaded
// is a three step process:
// moving the entries to a separate list, handshake to wait for
// readers to complete (see NSV here), and then actually deleting the entries.
// Deleting entries is done by the ServiceThread when triggered by class unloading.
bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
assert(Thread::current()->is_Java_thread() || SafepointSynchronize::is_at_safepoint(),
"can only be called by a JavaThread or at safepoint");
// This cannot safepoint while reading the protection domain set.
NoSafepointVerifier nsv;
#ifdef ASSERT #ifdef ASSERT
if (protection_domain == instance_klass()->protection_domain()) { if (protection_domain == instance_klass()->protection_domain()) {
MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
// Ensure this doesn't show up in the pd_set (invariant) // Ensure this doesn't show up in the pd_set (invariant)
bool in_pd_set = false; bool in_pd_set = false;
for (ProtectionDomainEntry* current = pd_set(); for (ProtectionDomainEntry* current = pd_set_acquire();
current != NULL; current != NULL;
current = current->next()) { current = current->next_acquire()) {
if (current->object_no_keepalive() == protection_domain) { if (current->object_no_keepalive() == protection_domain) {
in_pd_set = true; in_pd_set = true;
break; break;
@ -167,12 +178,9 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
return true; return true;
} }
// Lock the pd_set list. This lock cannot safepoint since the caller holds for (ProtectionDomainEntry* current = pd_set_acquire();
// a Dictionary entry, which can be moved if the Dictionary is resized.
MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag);
for (ProtectionDomainEntry* current = pd_set();
current != NULL; current != NULL;
current = current->next()) { current = current->next_acquire()) {
if (current->object_no_keepalive() == protection_domain) { if (current->object_no_keepalive() == protection_domain) {
return true; return true;
} }
@ -180,17 +188,13 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
return false; return false;
} }
void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) { void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
if (!contains_protection_domain(protection_domain())) { if (!contains_protection_domain(protection_domain())) {
ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain); ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
// The pd_set in the dictionary entry is protected by a low level lock. // Additions and deletions hold the SystemDictionary_lock, readers are lock-free
// With concurrent PD table cleanup, these links could be broken. ProtectionDomainEntry* new_head = new ProtectionDomainEntry(entry, _pd_set);
MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag); release_set_pd_set(new_head);
ProtectionDomainEntry* new_head =
new ProtectionDomainEntry(entry, pd_set());
set_pd_set(new_head);
} }
LogTarget(Trace, protectiondomain) lt; LogTarget(Trace, protectiondomain) lt;
if (lt.is_enabled()) { if (lt.is_enabled()) {
@ -420,8 +424,9 @@ void Dictionary::validate_protection_domain(unsigned int name_hash,
// During class loading we may have cached a protection domain that has // During class loading we may have cached a protection domain that has
// since been unreferenced, so this entry should be cleared. // since been unreferenced, so this entry should be cleared.
void Dictionary::clean_cached_protection_domains() { void Dictionary::clean_cached_protection_domains(GrowableArray<ProtectionDomainEntry*>* delete_list) {
assert_locked_or_safepoint(SystemDictionary_lock); assert(Thread::current()->is_Java_thread(), "only called by JavaThread");
assert_lock_strong(SystemDictionary_lock);
assert(!loader_data()->has_class_mirror_holder(), "cld should have a ClassLoader holder not a Class holder"); assert(!loader_data()->has_class_mirror_holder(), "cld should have a ClassLoader holder not a Class holder");
if (loader_data()->is_the_null_class_loader_data()) { if (loader_data()->is_the_null_class_loader_data()) {
@ -435,8 +440,7 @@ void Dictionary::clean_cached_protection_domains() {
probe = probe->next()) { probe = probe->next()) {
Klass* e = probe->instance_klass(); Klass* e = probe->instance_klass();
MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag); ProtectionDomainEntry* current = probe->pd_set_acquire();
ProtectionDomainEntry* current = probe->pd_set();
ProtectionDomainEntry* prev = NULL; ProtectionDomainEntry* prev = NULL;
while (current != NULL) { while (current != NULL) {
if (current->object_no_keepalive() == NULL) { if (current->object_no_keepalive() == NULL) {
@ -450,18 +454,19 @@ void Dictionary::clean_cached_protection_domains() {
ls.print(" loading: "); probe->instance_klass()->print_value_on(&ls); ls.print(" loading: "); probe->instance_klass()->print_value_on(&ls);
ls.cr(); ls.cr();
} }
if (probe->pd_set() == current) { if (probe->pd_set_acquire() == current) {
probe->set_pd_set(current->next()); probe->release_set_pd_set(current->next_acquire());
} else { } else {
assert(prev != NULL, "should be set by alive entry"); assert(prev != NULL, "should be set by alive entry");
prev->set_next(current->next()); prev->release_set_next(current->next_acquire());
} }
ProtectionDomainEntry* to_delete = current; // Mark current for deletion but in the meantime it can still be
current = current->next(); // traversed.
delete to_delete; delete_list->push(current);
current = current->next_acquire();
} else { } else {
prev = current; prev = current;
current = current->next(); current = current->next_acquire();
} }
} }
} }
@ -552,20 +557,20 @@ void SymbolPropertyTable::free_entry(SymbolPropertyEntry* entry) {
} }
void DictionaryEntry::verify_protection_domain_set() { void DictionaryEntry::verify_protection_domain_set() {
MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag); assert(SafepointSynchronize::is_at_safepoint(), "must only be called as safepoint");
for (ProtectionDomainEntry* current = pd_set(); // accessed at a safepoint for (ProtectionDomainEntry* current = pd_set_acquire(); // accessed at a safepoint
current != NULL; current != NULL;
current = current->_next) { current = current->next_acquire()) {
guarantee(oopDesc::is_oop_or_null(current->_pd_cache->object_no_keepalive()), "Invalid oop"); guarantee(oopDesc::is_oop_or_null(current->object_no_keepalive()), "Invalid oop");
} }
} }
void DictionaryEntry::print_count(outputStream *st) { void DictionaryEntry::print_count(outputStream *st) {
MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag); assert_locked_or_safepoint(SystemDictionary_lock);
int count = 0; int count = 0;
for (ProtectionDomainEntry* current = pd_set(); // accessed inside SD lock for (ProtectionDomainEntry* current = pd_set_acquire();
current != NULL; current != NULL;
current = current->_next) { current = current->next_acquire()) {
count++; count++;
} }
st->print_cr("pd set count = #%d", count); st->print_cr("pd set count = #%d", count);
@ -596,6 +601,8 @@ void Dictionary::print_on(outputStream* st) const {
// redundant and obvious. // redundant and obvious.
st->print(", "); st->print(", ");
cld->print_value_on(st); cld->print_value_on(st);
st->print(", ");
probe->print_count(st);
} }
st->cr(); st->cr();
} }

View file

@ -33,6 +33,7 @@
class DictionaryEntry; class DictionaryEntry;
class ProtectionDomainEntry; class ProtectionDomainEntry;
template <typename T> class GrowableArray;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The data structure for the class loader data dictionaries. // The data structure for the class loader data dictionaries.
@ -67,7 +68,7 @@ public:
void all_entries_do(KlassClosure* closure); void all_entries_do(KlassClosure* closure);
void classes_do(MetaspaceClosure* it); void classes_do(MetaspaceClosure* it);
void clean_cached_protection_domains(); void clean_cached_protection_domains(GrowableArray<ProtectionDomainEntry*>* delete_list);
// Protection domains // Protection domains
InstanceKlass* find(unsigned int hash, Symbol* name, Handle protection_domain); InstanceKlass* find(unsigned int hash, Symbol* name, Handle protection_domain);
@ -111,18 +112,11 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
// Contains the set of approved protection domains that can access // Contains the set of approved protection domains that can access
// this dictionary entry. // this dictionary entry.
// //
// This protection domain set is a set of tuples:
//
// (InstanceKlass C, initiating class loader ICL, Protection Domain PD)
//
// [Note that C.protection_domain(), which is stored in the java.lang.Class // [Note that C.protection_domain(), which is stored in the java.lang.Class
// mirror of C, is NOT the same as PD] // mirror of C, is NOT the same as PD]
// //
// If such an entry (C, ICL, PD) exists in the table, it means that // If an entry for PD exists in the list, it means that
// it is okay for a class Foo to reference C, where // it is okay for a caller class to reference the class in this dictionary entry.
//
// Foo.protection_domain() == PD, and
// Foo's defining class loader == ICL
// //
// The usage of the PD set can be seen in SystemDictionary::validate_protection_domain() // The usage of the PD set can be seen in SystemDictionary::validate_protection_domain()
// It is essentially a cache to avoid repeated Java up-calls to // It is essentially a cache to avoid repeated Java up-calls to
@ -147,8 +141,8 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
return (DictionaryEntry**)HashtableEntry<InstanceKlass*, mtClass>::next_addr(); return (DictionaryEntry**)HashtableEntry<InstanceKlass*, mtClass>::next_addr();
} }
ProtectionDomainEntry* pd_set() const { return _pd_set; } ProtectionDomainEntry* pd_set_acquire() const { return Atomic::load_acquire(&_pd_set); }
void set_pd_set(ProtectionDomainEntry* new_head) { _pd_set = new_head; } void release_set_pd_set(ProtectionDomainEntry* entry) { Atomic::release_store(&_pd_set, entry); }
// Tells whether the initiating class' protection domain can access the klass in this entry // Tells whether the initiating class' protection domain can access the klass in this entry
inline bool is_valid_protection_domain(Handle protection_domain); inline bool is_valid_protection_domain(Handle protection_domain);

View file

@ -34,6 +34,8 @@
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "oops/weakHandle.inline.hpp" #include "oops/weakHandle.inline.hpp"
#include "runtime/atomic.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp" #include "utilities/hashtable.inline.hpp"
unsigned int ProtectionDomainCacheTable::compute_hash(Handle protection_domain) { unsigned int ProtectionDomainCacheTable::compute_hash(Handle protection_domain) {
@ -58,18 +60,61 @@ void ProtectionDomainCacheTable::trigger_cleanup() {
} }
class CleanProtectionDomainEntries : public CLDClosure { class CleanProtectionDomainEntries : public CLDClosure {
GrowableArray<ProtectionDomainEntry*>* _delete_list;
public:
CleanProtectionDomainEntries(GrowableArray<ProtectionDomainEntry*>* delete_list) :
_delete_list(delete_list) {}
void do_cld(ClassLoaderData* data) { void do_cld(ClassLoaderData* data) {
Dictionary* dictionary = data->dictionary(); Dictionary* dictionary = data->dictionary();
if (dictionary != NULL) { if (dictionary != NULL) {
dictionary->clean_cached_protection_domains(); dictionary->clean_cached_protection_domains(_delete_list);
} }
} }
}; };
static GrowableArray<ProtectionDomainEntry*>* _delete_list = NULL;
class HandshakeForPD : public HandshakeClosure {
public:
HandshakeForPD() : HandshakeClosure("HandshakeForPD") {}
void do_thread(Thread* thread) {
log_trace(protectiondomain)("HandshakeForPD::do_thread: thread="
INTPTR_FORMAT, p2i(thread));
}
};
static void purge_deleted_entries() {
// If there are any deleted entries, Handshake-all then they'll be
// safe to remove since traversing the pd_set list does not stop for
// safepoints and only JavaThreads will read the pd_set.
// This is actually quite rare because the protection domain is generally associated
// with the caller class and class loader, which if still alive will keep this
// protection domain entry alive.
if (_delete_list->length() >= 10) {
HandshakeForPD hs_pd;
Handshake::execute(&hs_pd);
for (int i = _delete_list->length() - 1; i >= 0; i--) {
ProtectionDomainEntry* entry = _delete_list->at(i);
_delete_list->remove_at(i);
delete entry;
}
assert(_delete_list->length() == 0, "should be cleared");
}
}
void ProtectionDomainCacheTable::unlink() { void ProtectionDomainCacheTable::unlink() {
// The dictionary entries _pd_set field should be null also, so nothing to do. // The dictionary entries _pd_set field should be null also, so nothing to do.
assert(java_lang_System::allow_security_manager(), "should not be called otherwise"); assert(java_lang_System::allow_security_manager(), "should not be called otherwise");
// Create a list for holding deleted entries
if (_delete_list == NULL) {
_delete_list = new (ResourceObj::C_HEAP, mtClass)
GrowableArray<ProtectionDomainEntry*>(20, mtClass);
}
{ {
// First clean cached pd lists in loaded CLDs // First clean cached pd lists in loaded CLDs
// It's unlikely, but some loaded classes in a dictionary might // It's unlikely, but some loaded classes in a dictionary might
@ -77,10 +122,13 @@ void ProtectionDomainCacheTable::unlink() {
// The dictionary pd_set points at entries in the ProtectionDomainCacheTable. // The dictionary pd_set points at entries in the ProtectionDomainCacheTable.
MutexLocker ml(ClassLoaderDataGraph_lock); MutexLocker ml(ClassLoaderDataGraph_lock);
MutexLocker mldict(SystemDictionary_lock); // need both. MutexLocker mldict(SystemDictionary_lock); // need both.
CleanProtectionDomainEntries clean; CleanProtectionDomainEntries clean(_delete_list);
ClassLoaderDataGraph::loaded_cld_do(&clean); ClassLoaderDataGraph::loaded_cld_do(&clean);
} }
// Purge any deleted entries outside of the SystemDictionary_lock.
purge_deleted_entries();
MutexLocker ml(SystemDictionary_lock); MutexLocker ml(SystemDictionary_lock);
int oops_removed = 0; int oops_removed = 0;
for (int i = 0; i < table_size(); ++i) { for (int i = 0; i < table_size(); ++i) {
@ -129,10 +177,6 @@ oop ProtectionDomainCacheEntry::object() {
return literal().resolve(); return literal().resolve();
} }
oop ProtectionDomainEntry::object() {
return _pd_cache->object();
}
// The object_no_keepalive() call peeks at the phantomly reachable oop without // The object_no_keepalive() call peeks at the phantomly reachable oop without
// keeping it alive. This is okay to do in the VM thread state if it is not // keeping it alive. This is okay to do in the VM thread state if it is not
// leaked out to become strongly reachable. // leaked out to become strongly reachable.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
#include "oops/oop.hpp" #include "oops/oop.hpp"
#include "oops/weakHandle.hpp" #include "oops/weakHandle.hpp"
#include "memory/iterator.hpp" #include "runtime/atomic.hpp"
#include "utilities/hashtable.hpp" #include "utilities/hashtable.hpp"
// This class caches the approved protection domains that can access loaded classes. // This class caches the approved protection domains that can access loaded classes.
@ -62,8 +62,6 @@ class ProtectionDomainCacheEntry : public HashtableEntry<WeakHandle, mtClass> {
// The amount of different protection domains used is typically magnitudes smaller // The amount of different protection domains used is typically magnitudes smaller
// than the number of system dictionary entries (loaded classes). // than the number of system dictionary entries (loaded classes).
class ProtectionDomainCacheTable : public Hashtable<WeakHandle, mtClass> { class ProtectionDomainCacheTable : public Hashtable<WeakHandle, mtClass> {
friend class VMStructs;
private:
ProtectionDomainCacheEntry* bucket(int i) const { ProtectionDomainCacheEntry* bucket(int i) const {
return (ProtectionDomainCacheEntry*) Hashtable<WeakHandle, mtClass>::bucket(i); return (ProtectionDomainCacheEntry*) Hashtable<WeakHandle, mtClass>::bucket(i);
} }
@ -104,20 +102,17 @@ public:
}; };
// This describes the linked list protection domain for each DictionaryEntry in pd_set.
class ProtectionDomainEntry :public CHeapObj<mtClass> { class ProtectionDomainEntry :public CHeapObj<mtClass> {
friend class VMStructs;
public:
ProtectionDomainEntry* _next;
ProtectionDomainCacheEntry* _pd_cache; ProtectionDomainCacheEntry* _pd_cache;
ProtectionDomainEntry* volatile _next;
public:
ProtectionDomainEntry(ProtectionDomainCacheEntry* pd_cache, ProtectionDomainEntry* next) { ProtectionDomainEntry(ProtectionDomainCacheEntry* pd_cache,
_pd_cache = pd_cache; ProtectionDomainEntry* head) : _pd_cache(pd_cache), _next(head) {}
_next = next;
}
ProtectionDomainEntry* next() { return _next; } ProtectionDomainEntry* next_acquire() { return Atomic::load_acquire(&_next); }
void set_next(ProtectionDomainEntry* entry) { _next = entry; } void release_set_next(ProtectionDomainEntry* entry) { Atomic::release_store(&_next, entry); }
oop object();
oop object_no_keepalive(); oop object_no_keepalive();
}; };
#endif // SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP #endif // SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP

View file

@ -42,7 +42,6 @@
Mutex* Patching_lock = NULL; Mutex* Patching_lock = NULL;
Mutex* CompiledMethod_lock = NULL; Mutex* CompiledMethod_lock = NULL;
Monitor* SystemDictionary_lock = NULL; Monitor* SystemDictionary_lock = NULL;
Mutex* ProtectionDomainSet_lock = NULL;
Mutex* SharedDictionary_lock = NULL; Mutex* SharedDictionary_lock = NULL;
Mutex* Module_lock = NULL; Mutex* Module_lock = NULL;
Mutex* CompiledIC_lock = NULL; Mutex* CompiledIC_lock = NULL;
@ -261,7 +260,6 @@ void mutex_init() {
def(JmethodIdCreation_lock , PaddedMutex , special-2, true, _safepoint_check_never); // used for creating jmethodIDs. def(JmethodIdCreation_lock , PaddedMutex , special-2, true, _safepoint_check_never); // used for creating jmethodIDs.
def(SystemDictionary_lock , PaddedMonitor, leaf, true, _safepoint_check_always); def(SystemDictionary_lock , PaddedMonitor, leaf, true, _safepoint_check_always);
def(ProtectionDomainSet_lock , PaddedMutex , leaf-1, true, _safepoint_check_never);
def(SharedDictionary_lock , PaddedMutex , leaf, true, _safepoint_check_always); def(SharedDictionary_lock , PaddedMutex , leaf, true, _safepoint_check_always);
def(Module_lock , PaddedMutex , leaf+2, false, _safepoint_check_always); def(Module_lock , PaddedMutex , leaf+2, false, _safepoint_check_always);
def(InlineCacheBuffer_lock , PaddedMutex , leaf, true, _safepoint_check_never); def(InlineCacheBuffer_lock , PaddedMutex , leaf, true, _safepoint_check_never);

View file

@ -34,7 +34,6 @@
extern Mutex* Patching_lock; // a lock used to guard code patching of compiled code extern Mutex* Patching_lock; // a lock used to guard code patching of compiled code
extern Mutex* CompiledMethod_lock; // a lock used to guard a compiled method and OSR queues extern Mutex* CompiledMethod_lock; // a lock used to guard a compiled method and OSR queues
extern Monitor* SystemDictionary_lock; // a lock on the system dictionary extern Monitor* SystemDictionary_lock; // a lock on the system dictionary
extern Mutex* ProtectionDomainSet_lock; // a lock on the pd_set list in the system dictionary
extern Mutex* SharedDictionary_lock; // a lock on the CDS shared dictionary extern Mutex* SharedDictionary_lock; // a lock on the CDS shared dictionary
extern Mutex* Module_lock; // a lock on module and package related data structures extern Mutex* Module_lock; // a lock on module and package related data structures
extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -37,7 +37,7 @@ public class ClassForName {
public ClassForName() { public ClassForName() {
try { try {
// class_loader = URLClassLoader, protection_domain = ClassForName.getProtectionDomain() // class_loader = App$ClassLoader, protection_domain = ClassForName.getProtectionDomain()
Class.forName(java.util.List.class.getName(), false, Class.forName(java.util.List.class.getName(), false,
ClassLoader.getSystemClassLoader()); ClassLoader.getSystemClassLoader());
} catch (Throwable e) { } catch (Throwable e) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -84,7 +84,9 @@ public class ProtectionDomainCacheTest {
CLASSFILENAME); CLASSFILENAME);
Files.delete(classFile); Files.delete(classFile);
for (int i = 0; i < 20; i++) {
loadAndRun(jarFilePath); loadAndRun(jarFilePath);
}
// Give the GC a chance to unload protection domains // Give the GC a chance to unload protection domains
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
@ -101,11 +103,12 @@ public class ProtectionDomainCacheTest {
"-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockDiagnosticVMOptions",
"-XX:VerifySubSet=dictionary", "-XX:VerifySubSet=dictionary",
"-XX:+VerifyAfterGC", "-XX:+VerifyAfterGC",
"-Xlog:gc+verify,protectiondomain=debug", "-Xlog:gc+verify,protectiondomain=trace",
"-Djava.security.manager", "-Djava.security.manager",
Test.class.getName()); Test.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start()); OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("PD in set is not alive"); output.shouldContain("PD in set is not alive");
output.shouldContain("HandshakeForPD::do_thread");
output.shouldHaveExitValue(0); output.shouldHaveExitValue(0);
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -43,7 +43,14 @@
* @comment build test class and indify classes * @comment build test class and indify classes
* @build vm.mlvm.mixed.stress.java.findDeadlock.INDIFY_Test * @build vm.mlvm.mixed.stress.java.findDeadlock.INDIFY_Test
* @run driver vm.mlvm.share.IndifiedClassesBuilder * @run driver vm.mlvm.share.IndifiedClassesBuilder
*
* @run main/othervm -Xlog:gc,safepoint vm.mlvm.mixed.stress.java.findDeadlock.INDIFY_Test * @run main/othervm -Xlog:gc,safepoint vm.mlvm.mixed.stress.java.findDeadlock.INDIFY_Test
*
* To see code that takes more time to safepoint run with:
* main/othervm -XX:+SafepointTimeout -XX:+UnlockDiagnosticVMOptions
* -XX:+AbortVMOnSafepointTimeout
* -XX:SafepointTimeoutDelay=500
* -XX:+PrintSystemDictionaryAtExit
* -Xlog:gc,safepoint
* vm.mlvm.mixed.stress.java.findDeadlock.INDIFY_Test
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -109,7 +109,7 @@ public class Indify {
public boolean keepgoing = false; public boolean keepgoing = false;
public boolean expandProperties = false; public boolean expandProperties = false;
public boolean overwrite = false; public boolean overwrite = false;
public boolean quiet = false; public boolean quiet = true;
public boolean verbose = false; public boolean verbose = false;
public boolean transitionalJSR292 = true; // default to false later public boolean transitionalJSR292 = true; // default to false later
public boolean all = false; public boolean all = false;