--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -35,6 +35,7 @@
#include "classfile/loaderConstraints.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/placeholders.hpp"
+#include "classfile/protectionDomainCache.hpp"
#include "classfile/resolutionErrors.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -88,19 +89,14 @@
#include "trace/tracing.hpp"
#endif
-Dictionary* SystemDictionary::_dictionary = NULL;
PlaceholderTable* SystemDictionary::_placeholders = NULL;
Dictionary* SystemDictionary::_shared_dictionary = NULL;
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
-
+ProtectionDomainCacheTable* SystemDictionary::_pd_cache_table = NULL;
int SystemDictionary::_number_of_modifications = 0;
-int SystemDictionary::_sdgeneration = 0;
-const int SystemDictionary::_primelist[_prime_array_size] = {1009,2017,4049,5051,10103,
- 20201,40423,99991};
-
oop SystemDictionary::_system_loader_lock_obj = NULL;
InstanceKlass* SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT]
@@ -116,6 +112,10 @@
// lazily initialized klass variables
InstanceKlass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL;
+// Default ProtectionDomainCacheSize value
+
+const int defaultProtectionDomainCacheSize = 1009;
+
// ----------------------------------------------------------------------------
// Java-level SystemLoader
@@ -343,32 +343,32 @@
#endif // INCLUDE_CDS
// Double-check, if child class is already loaded, just return super-class,interface
- // Don't add a placedholder if already loaded, i.e. already in system dictionary
+ // Don't add a placedholder if already loaded, i.e. already in appropriate class loader
+ // dictionary.
// Make sure there's a placeholder for the *child* before resolving.
// Used as a claim that this thread is currently loading superclass/classloader
// Used here for ClassCircularity checks and also for heap verification
- // (every InstanceKlass in the heap needs to be in the system dictionary
- // or have a placeholder).
- // Must check ClassCircularity before checking if super class is already loaded
+ // (every InstanceKlass needs to be in its class loader dictionary or have a placeholder).
+ // Must check ClassCircularity before checking if super class is already loaded.
//
// We might not already have a placeholder if this child_name was
// first seen via resolve_from_stream (jni_DefineClass or JVM_DefineClass);
// the name of the class might not be known until the stream is actually
// parsed.
// Bugs 4643874, 4715493
- // compute_hash can have a safepoint
ClassLoaderData* loader_data = class_loader_data(class_loader);
- unsigned int d_hash = dictionary()->compute_hash(child_name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- unsigned int p_hash = placeholders()->compute_hash(child_name, loader_data);
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(child_name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ unsigned int p_hash = placeholders()->compute_hash(child_name);
int p_index = placeholders()->hash_to_index(p_hash);
// can't throw error holding a lock
bool child_already_loaded = false;
bool throw_circularity_error = false;
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- Klass* childk = find_class(d_index, d_hash, child_name, loader_data);
+ Klass* childk = find_class(d_index, d_hash, child_name, dictionary);
Klass* quicksuperk;
// to support // loading: if child done loading, just return superclass
// if class_name, & class_loader don't match:
@@ -445,13 +445,18 @@
ls.cr();
}
+ // This handle and the class_loader handle passed in keeps this class from
+ // being unloaded through several GC points.
+ // The class_loader handle passed in is the initiating loader.
+ Handle mirror(THREAD, klass->java_mirror());
+
InstanceKlass* system_loader = SystemDictionary::ClassLoader_klass();
JavaCalls::call_special(&result,
class_loader,
system_loader,
vmSymbols::checkPackageAccess_name(),
vmSymbols::class_protectiondomain_signature(),
- Handle(THREAD, klass->java_mirror()),
+ mirror,
protection_domain,
THREAD);
@@ -466,27 +471,16 @@
// If no exception has been thrown, we have validated the protection domain
// Insert the protection domain of the initiating class into the set.
{
- // We recalculate the entry here -- we've called out to java since
- // the last time it was calculated.
ClassLoaderData* loader_data = class_loader_data(class_loader);
+ Dictionary* dictionary = loader_data->dictionary();
Symbol* kn = klass->name();
- unsigned int d_hash = dictionary()->compute_hash(kn, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
+ unsigned int d_hash = dictionary->compute_hash(kn);
+ int d_index = dictionary->hash_to_index(d_hash);
MutexLocker mu(SystemDictionary_lock, THREAD);
- {
- // Note that we have an entry, and entries can be deleted only during GC,
- // so we cannot allow GC to occur while we're holding this entry.
-
- // We're using a NoSafepointVerifier to catch any place where we
- // might potentially do a GC at all.
- // Dictionary::do_unloading() asserts that classes in SD are only
- // unloaded at a safepoint. Anonymous classes are not in SD.
- NoSafepointVerifier nosafepoint;
- dictionary()->add_protection_domain(d_index, d_hash, klass, loader_data,
- protection_domain, THREAD);
- }
+ dictionary->add_protection_domain(d_index, d_hash, klass,
+ protection_domain, THREAD);
}
}
@@ -548,9 +542,10 @@
Handle protection_domain, Handle lockObject, TRAPS) {
ClassLoaderData* loader_data = class_loader_data(class_loader);
- unsigned int d_hash = dictionary()->compute_hash(name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- unsigned int p_hash = placeholders()->compute_hash(name, loader_data);
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ unsigned int p_hash = placeholders()->compute_hash(name);
int p_index = placeholders()->hash_to_index(p_hash);
// superk is not used, resolve_super called for circularity check only
@@ -573,7 +568,7 @@
if (!class_loader.is_null() && is_parallelCapable(class_loader)) {
MutexLocker mu(SystemDictionary_lock, THREAD);
// Check if classloading completed while we were loading superclass or waiting
- return find_class(d_index, d_hash, name, loader_data);
+ return find_class(d_index, d_hash, name, dictionary);
}
// must loop to both handle other placeholder updates
@@ -583,7 +578,7 @@
while (super_load_in_progress) {
MutexLocker mu(SystemDictionary_lock, THREAD);
// Check if classloading completed while we were loading superclass or waiting
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
return check;
@@ -663,6 +658,7 @@
// Fix for 4474172; see evaluation for more details
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL);
+ Dictionary* dictionary = loader_data->dictionary();
// Do lookup to see if class already exist and the protection domain
// has the right access
@@ -670,10 +666,9 @@
// All subsequent calls use find_class, and set has_loaded_class so that
// before we return a result we call out to java to check for valid protection domain
// to allow returning the Klass* and add it to the pd_set if it is valid
- unsigned int d_hash = dictionary()->compute_hash(name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- Klass* probe = dictionary()->find(d_index, d_hash, name, loader_data,
- protection_domain, THREAD);
+ unsigned int d_hash = dictionary->compute_hash(name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ Klass* probe = dictionary->find(d_index, d_hash, name, protection_domain);
if (probe != NULL) return probe;
@@ -691,7 +686,7 @@
DoObjectLock = false;
}
- unsigned int p_hash = placeholders()->compute_hash(name, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(name);
int p_index = placeholders()->hash_to_index(p_hash);
// Class is not in SystemDictionary so we have to do loading.
@@ -710,7 +705,7 @@
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
class_has_been_loaded = true;
@@ -794,7 +789,7 @@
double_lock_wait(lockObject, THREAD);
}
// Check if classloading completed while we were waiting
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
k = check;
@@ -819,7 +814,7 @@
// i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL
// one final check if the load has already completed
// class loaders holding the ObjectLock shouldn't find the class here
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so return it after checking/adding protection domain
k = check;
@@ -852,7 +847,7 @@
if (k == NULL && HAS_PENDING_EXCEPTION
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just use it
k = check;
@@ -886,7 +881,7 @@
}
}
}
- } // load_instance_class loop
+ } // load_instance_class
if (load_instance_added == true) {
// clean up placeholder entries for LOAD_INSTANCE success or error
@@ -919,16 +914,8 @@
// Check the protection domain has the right access
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- // Note that we have an entry, and entries can be deleted only during GC,
- // so we cannot allow GC to occur while we're holding this entry.
- // We're using a NoSafepointVerifier to catch any place where we
- // might potentially do a GC at all.
- // Dictionary::do_unloading() asserts that classes in SD are only
- // unloaded at a safepoint. Anonymous classes are not in SD.
- NoSafepointVerifier nosafepoint;
- if (dictionary()->is_valid_protection_domain(d_index, d_hash, name,
- loader_data,
- protection_domain)) {
+ if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
+ protection_domain)) {
return k;
}
}
@@ -968,20 +955,11 @@
return NULL;
}
- unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
-
- {
- // Note that we have an entry, and entries can be deleted only during GC,
- // so we cannot allow GC to occur while we're holding this entry.
- // We're using a NoSafepointVerifier to catch any place where we
- // might potentially do a GC at all.
- // Dictionary::do_unloading() asserts that classes in SD are only
- // unloaded at a safepoint. Anonymous classes are not in SD.
- NoSafepointVerifier nosafepoint;
- return dictionary()->find(d_index, d_hash, class_name, loader_data,
- protection_domain, THREAD);
- }
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(class_name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ return dictionary->find(d_index, d_hash, class_name,
+ protection_domain);
}
@@ -1035,7 +1013,6 @@
guarantee(host_klass->class_loader() == class_loader(), "should be the same");
guarantee(!DumpSharedSpaces, "must not create anonymous classes when dumping");
loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
- loader_data->record_dependency(host_klass, CHECK_NULL);
} else {
loader_data = ClassLoaderData::class_loader_data(class_loader());
}
@@ -1066,7 +1043,7 @@
// deoptimizations.
add_to_hierarchy(k, CHECK_NULL); // No exception, but can block
- // But, do not add to system dictionary.
+ // But, do not add to dictionary.
// compiled code dependencies need to be validated anyway
notice_modification();
@@ -1189,9 +1166,10 @@
#if INCLUDE_CDS
void SystemDictionary::set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
int number_of_entries) {
- assert(length == _nof_buckets * sizeof(HashtableBucket<mtClass>),
+ assert(length == _shared_dictionary_size * sizeof(HashtableBucket<mtClass>),
"bad shared dictionary size.");
- _shared_dictionary = new Dictionary(_nof_buckets, t, number_of_entries);
+ _shared_dictionary = new Dictionary(ClassLoaderData::the_null_class_loader_data(),
+ _shared_dictionary_size, t, number_of_entries);
}
@@ -1200,7 +1178,7 @@
InstanceKlass* SystemDictionary::find_shared_class(Symbol* class_name) {
if (shared_dictionary() != NULL) {
- unsigned int d_hash = shared_dictionary()->compute_hash(class_name, NULL);
+ unsigned int d_hash = shared_dictionary()->compute_hash(class_name);
int d_index = shared_dictionary()->hash_to_index(d_hash);
return shared_dictionary()->find_shared_class(d_index, d_hash, class_name);
@@ -1626,8 +1604,9 @@
// Parallel classloaders will call find_or_define_instance_class
// which will require a token to perform the define class
Symbol* name_h = k->name();
- unsigned int d_hash = dictionary()->compute_hash(name_h, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(name_h);
+ int d_index = dictionary->hash_to_index(d_hash);
check_constraints(d_index, d_hash, k, class_loader_h, true, CHECK);
// Register class just loaded with class loader (placed in Vector)
@@ -1645,7 +1624,7 @@
// Add the new class. We need recompile lock during update of CHA.
{
- unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(name_h);
int p_index = placeholders()->hash_to_index(p_hash);
MutexLocker mu_r(Compile_lock, THREAD);
@@ -1695,12 +1674,13 @@
Symbol* name_h = k->name(); // passed in class_name may be null
ClassLoaderData* loader_data = class_loader_data(class_loader);
+ Dictionary* dictionary = loader_data->dictionary();
- unsigned int d_hash = dictionary()->compute_hash(name_h, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
+ unsigned int d_hash = dictionary->compute_hash(name_h);
+ int d_index = dictionary->hash_to_index(d_hash);
// Hold SD lock around find_class and placeholder creation for DEFINE_CLASS
- unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(name_h);
int p_index = placeholders()->hash_to_index(p_hash);
PlaceholderEntry* probe;
@@ -1708,7 +1688,7 @@
MutexLocker mu(SystemDictionary_lock, THREAD);
// First check if class already defined
if (UnsyncloadClass || (is_parallelDefine(class_loader))) {
- InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
if (check != NULL) {
return check;
}
@@ -1730,7 +1710,7 @@
placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD);
SystemDictionary_lock->notify_all();
#ifdef ASSERT
- InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
assert(check != NULL, "definer missed recording success");
#endif
return probe->instance_klass();
@@ -1769,6 +1749,7 @@
return k;
}
+
Handle SystemDictionary::compute_loader_lock_object(Handle class_loader, TRAPS) {
// If class_loader is NULL we synchronize on _system_loader_lock_obj
if (class_loader.is_null()) {
@@ -1806,12 +1787,9 @@
InstanceKlass* SystemDictionary::find_class(int index, unsigned int hash,
Symbol* class_name,
- ClassLoaderData* loader_data) {
+ Dictionary* dictionary) {
assert_locked_or_safepoint(SystemDictionary_lock);
- assert (index == dictionary()->index_for(class_name, loader_data),
- "incorrect index?");
-
- return dictionary()->find_class(index, hash, class_name, loader_data);
+ return dictionary->find_class(index, hash, class_name);
}
@@ -1819,14 +1797,17 @@
Symbol* SystemDictionary::find_placeholder(Symbol* class_name,
ClassLoaderData* loader_data) {
assert_locked_or_safepoint(SystemDictionary_lock);
- unsigned int p_hash = placeholders()->compute_hash(class_name, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(class_name);
int p_index = placeholders()->hash_to_index(p_hash);
return placeholders()->find_entry(p_index, p_hash, class_name, loader_data);
}
// Used for assertions and verification only
+// Precalculating the hash and index is an optimization because there are many lookups
+// before adding the class.
InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) {
+ assert_locked_or_safepoint(SystemDictionary_lock);
#ifndef ASSERT
guarantee(VerifyBeforeGC ||
VerifyDuringGC ||
@@ -1834,18 +1815,11 @@
VerifyDuringStartup ||
VerifyAfterGC, "too expensive");
#endif
- assert_locked_or_safepoint(SystemDictionary_lock);
- // First look in the loaded class array
- unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- return find_class(d_index, d_hash, class_name, loader_data);
-}
-
-
-// Get the next class in the dictionary.
-Klass* SystemDictionary::try_get_next_class() {
- return dictionary()->try_get_next_class();
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(class_name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ return find_class(d_index, d_hash, class_name, dictionary);
}
@@ -1872,33 +1846,10 @@
// ----------------------------------------------------------------------------
// GC support
-// Following roots during mark-sweep is separated in two phases.
-//
-// The first phase follows preloaded classes and all other system
-// classes, since these will never get unloaded anyway.
-//
-// The second phase removes (unloads) unreachable classes from the
-// system dictionary and follows the remaining classes' contents.
-
void SystemDictionary::always_strong_oops_do(OopClosure* blk) {
roots_oops_do(blk, NULL);
}
-// Calculate a "good" systemdictionary size based
-// on predicted or current loaded classes count
-int SystemDictionary::calculate_systemdictionary_size(int classcount) {
- int newsize = _old_default_sdsize;
- if ((classcount > 0) && !DumpSharedSpaces) {
- int desiredsize = classcount/_average_depth_goal;
- for (newsize = _primelist[_sdgeneration]; _sdgeneration < _prime_array_size -1;
- newsize = _primelist[++_sdgeneration]) {
- if (desiredsize <= newsize) {
- break;
- }
- }
- }
- return newsize;
-}
#ifdef ASSERT
class VerifySDReachableAndLiveClosure : public OopClosure {
@@ -1907,7 +1858,7 @@
template <class T> void do_oop_work(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p);
- guarantee(_is_alive->do_object_b(obj), "Oop in system dictionary must be live");
+ guarantee(_is_alive->do_object_b(obj), "Oop in protection domain cache table must be live");
}
public:
@@ -1936,20 +1887,20 @@
if (unloading_occurred) {
GCTraceTime(Debug, gc, phases) t("Dictionary", gc_timer);
- dictionary()->do_unloading();
constraints()->purge_loader_constraints();
resolution_errors()->purge_resolution_errors();
}
{
GCTraceTime(Debug, gc, phases) t("ProtectionDomainCacheTable", gc_timer);
- // Oops referenced by the system dictionary may get unreachable independently
+ // Oops referenced by the protection domain cache table may get unreachable independently
// of the class loader (eg. cached protection domain oops). So we need to
- // explicitly unlink them here instead of in Dictionary::do_unloading.
- dictionary()->unlink(is_alive);
+ // explicitly unlink them here.
+ _pd_cache_table->unlink(is_alive);
+
#ifdef ASSERT
VerifySDReachableAndLiveClosure cl(is_alive);
- dictionary()->oops_do(&cl);
+ _pd_cache_table->oops_do(&cl);
#endif
}
@@ -1966,8 +1917,16 @@
strong->do_oop(&_system_loader_lock_obj);
CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);)
- // Adjust dictionary
- dictionary()->roots_oops_do(strong, weak);
+ // Do strong roots marking if the closures are the same.
+ if (strong == weak || !ClassUnloading) {
+ // Only the protection domain oops contain references into the heap. Iterate
+ // over all of them.
+ _pd_cache_table->oops_do(strong);
+ } else {
+ if (weak != NULL) {
+ _pd_cache_table->oops_do(weak);
+ }
+ }
// Visit extra methods
invoke_method_table()->oops_do(strong);
@@ -1982,8 +1941,9 @@
f->do_oop(&_system_loader_lock_obj);
CDS_ONLY(SystemDictionaryShared::oops_do(f);)
- // Adjust dictionary
- dictionary()->oops_do(f);
+ // Only the protection domain oops contain references into the heap. Iterate
+ // over all of them.
+ _pd_cache_table->oops_do(f);
// Visit extra methods
invoke_method_table()->oops_do(f);
@@ -1991,25 +1951,6 @@
ResolvedMethodTable::oops_do(f);
}
-// Just the classes from defining class loaders
-// Don't iterate over placeholders
-void SystemDictionary::classes_do(void f(Klass*)) {
- dictionary()->classes_do(f);
-}
-
-// Added for initialize_itable_for_klass
-// Just the classes from defining class loaders
-// Don't iterate over placeholders
-void SystemDictionary::classes_do(void f(Klass*, TRAPS), TRAPS) {
- dictionary()->classes_do(f, CHECK);
-}
-
-// All classes, and their class loaders
-// Don't iterate over placeholders
-void SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
- dictionary()->classes_do(f);
-}
-
void SystemDictionary::methods_do(void f(Method*)) {
// Walk methods in loaded classes
ClassLoaderDataGraph::methods_do(f);
@@ -2018,7 +1959,7 @@
}
void SystemDictionary::remove_classes_in_error_state() {
- dictionary()->remove_classes_in_error_state();
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->remove_classes_in_error_state();
}
// ----------------------------------------------------------------------------
@@ -2042,15 +1983,12 @@
void SystemDictionary::initialize(TRAPS) {
// Allocate arrays
- assert(dictionary() == NULL,
- "SystemDictionary should only be initialized once");
- _sdgeneration = 0;
- _dictionary = new Dictionary(calculate_systemdictionary_size(PredictedLoadedClassCount));
- _placeholders = new PlaceholderTable(_nof_buckets);
+ _placeholders = new PlaceholderTable(_placeholder_table_size);
_number_of_modifications = 0;
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
+ _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
// Allocate private object used as system class loader lock
_system_loader_lock_obj = oopFactory::new_intArray(0, CHECK);
@@ -2204,9 +2142,9 @@
// Constraints on class loaders. The details of the algorithm can be
// found in the OOPSLA'98 paper "Dynamic Class Loading in the Java
// Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is
-// that the system dictionary needs to maintain a set of contraints that
+// that the dictionary needs to maintain a set of contraints that
// must be satisfied by all classes in the dictionary.
-// if defining is true, then LinkageError if already in systemDictionary
+// if defining is true, then LinkageError if already in dictionary
// if initiating loader, then ok if InstanceKlass matches existing entry
void SystemDictionary::check_constraints(int d_index, unsigned int d_hash,
@@ -2221,12 +2159,12 @@
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, loader_data->dictionary());
if (check != NULL) {
// if different InstanceKlass - duplicate class definition,
// else - ok, class loaded by a different thread in parallel,
// we should only have found it if it was done loading and ok to use
- // system dictionary only holds instance classes, placeholders
+ // dictionary only holds instance classes, placeholders
// also holds array classes
assert(check->is_instance_klass(), "noninstance in systemdictionary");
@@ -2267,7 +2205,7 @@
}
-// Update system dictionary - done after check_constraint and add_to_hierachy
+// Update class loader data dictionary - done after check_constraint and add_to_hierachy
// have been called.
void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash,
int p_index, unsigned int p_hash,
@@ -2280,40 +2218,41 @@
ClassLoaderData *loader_data = class_loader_data(class_loader);
{
- MutexLocker mu1(SystemDictionary_lock, THREAD);
+ MutexLocker mu1(SystemDictionary_lock, THREAD);
- // See whether biased locking is enabled and if so set it for this
- // klass.
- // Note that this must be done past the last potential blocking
- // point / safepoint. We enable biased locking lazily using a
- // VM_Operation to iterate the SystemDictionary and installing the
- // biasable mark word into each InstanceKlass's prototype header.
- // To avoid race conditions where we accidentally miss enabling the
- // optimization for one class in the process of being added to the
- // dictionary, we must not safepoint after the test of
- // BiasedLocking::enabled().
- if (UseBiasedLocking && BiasedLocking::enabled()) {
- // Set biased locking bit for all loaded classes; it will be
- // cleared if revocation occurs too often for this type
- // NOTE that we must only do this when the class is initally
- // defined, not each time it is referenced from a new class loader
- if (k->class_loader() == class_loader()) {
- k->set_prototype_header(markOopDesc::biased_locking_prototype());
+ // See whether biased locking is enabled and if so set it for this
+ // klass.
+ // Note that this must be done past the last potential blocking
+ // point / safepoint. We enable biased locking lazily using a
+ // VM_Operation to iterate the SystemDictionary and installing the
+ // biasable mark word into each InstanceKlass's prototype header.
+ // To avoid race conditions where we accidentally miss enabling the
+ // optimization for one class in the process of being added to the
+ // dictionary, we must not safepoint after the test of
+ // BiasedLocking::enabled().
+ if (UseBiasedLocking && BiasedLocking::enabled()) {
+ // Set biased locking bit for all loaded classes; it will be
+ // cleared if revocation occurs too often for this type
+ // NOTE that we must only do this when the class is initally
+ // defined, not each time it is referenced from a new class loader
+ if (k->class_loader() == class_loader()) {
+ k->set_prototype_header(markOopDesc::biased_locking_prototype());
+ }
}
- }
- // Make a new system dictionary entry.
- InstanceKlass* sd_check = find_class(d_index, d_hash, name, loader_data);
- if (sd_check == NULL) {
- dictionary()->add_klass(name, loader_data, k);
- notice_modification();
- }
-#ifdef ASSERT
- sd_check = find_class(d_index, d_hash, name, loader_data);
- assert (sd_check != NULL, "should have entry in system dictionary");
- // Note: there may be a placeholder entry: for circularity testing
- // or for parallel defines
-#endif
+ // Make a new dictionary entry.
+ Dictionary* dictionary = loader_data->dictionary();
+ InstanceKlass* sd_check = find_class(d_index, d_hash, name, dictionary);
+ if (sd_check == NULL) {
+ dictionary->add_klass(d_index, d_hash, name, k);
+ notice_modification();
+ }
+ #ifdef ASSERT
+ sd_check = find_class(d_index, d_hash, name, dictionary);
+ assert (sd_check != NULL, "should have entry in dictionary");
+ // Note: there may be a placeholder entry: for circularity testing
+ // or for parallel defines
+ #endif
SystemDictionary_lock->notify_all();
}
}
@@ -2383,21 +2322,21 @@
constraint_name = fd.object_key();
}
}
- unsigned int d_hash1 = dictionary()->compute_hash(constraint_name, loader_data1);
- int d_index1 = dictionary()->hash_to_index(d_hash1);
- unsigned int d_hash2 = dictionary()->compute_hash(constraint_name, loader_data2);
- int d_index2 = dictionary()->hash_to_index(d_hash2);
- {
- MutexLocker mu_s(SystemDictionary_lock, THREAD);
+ Dictionary* dictionary1 = loader_data1->dictionary();
+ unsigned int d_hash1 = dictionary1->compute_hash(constraint_name);
+ int d_index1 = dictionary1->hash_to_index(d_hash1);
- // Better never do a GC while we're holding these oops
- NoSafepointVerifier nosafepoint;
+ Dictionary* dictionary2 = loader_data2->dictionary();
+ unsigned int d_hash2 = dictionary2->compute_hash(constraint_name);
+ int d_index2 = dictionary2->hash_to_index(d_hash2);
- InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, loader_data1);
- InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, loader_data2);
- return constraints()->add_entry(constraint_name, klass1, class_loader1,
- klass2, class_loader2);
+ {
+ MutexLocker mu_s(SystemDictionary_lock, THREAD);
+ InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, dictionary1);
+ InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, dictionary2);
+ return constraints()->add_entry(constraint_name, klass1, class_loader1,
+ klass2, class_loader2);
}
}
@@ -2847,64 +2786,73 @@
return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
}
-// Since the identity hash code for symbols changes when the symbols are
-// moved from the regular perm gen (hash in the mark word) to the shared
-// spaces (hash is the address), the classes loaded into the dictionary
-// may be in the wrong buckets.
+// Protection domain cache table handling
+
+ProtectionDomainCacheEntry* SystemDictionary::cache_get(Handle protection_domain) {
+ return _pd_cache_table->get(protection_domain);
+}
+
void SystemDictionary::reorder_dictionary() {
- dictionary()->reorder_dictionary();
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->reorder_dictionary();
}
void SystemDictionary::copy_buckets(char** top, char* end) {
- dictionary()->copy_buckets(top, end);
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->copy_buckets(top, end);
}
void SystemDictionary::copy_table(char** top, char* end) {
- dictionary()->copy_table(top, end);
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->copy_table(top, end);
}
-int SystemDictionary::number_of_classes() {
- return dictionary()->number_of_entries();
-}
-
-
// ----------------------------------------------------------------------------
void SystemDictionary::print_shared(bool details) {
shared_dictionary()->print(details);
}
void SystemDictionary::print(bool details) {
- dictionary()->print(details);
+ if (shared_dictionary() != NULL) {
+ tty->print_cr("Shared Dictionary");
+ shared_dictionary()->print(details);
+ }
+
+ GCMutexLocker mu(SystemDictionary_lock);
+
+ ClassLoaderDataGraph::print_dictionary(details);
// Placeholders
- GCMutexLocker mu(SystemDictionary_lock);
placeholders()->print();
+ tty->cr();
// loader constraints - print under SD_lock
constraints()->print();
+ tty->cr();
+
+ _pd_cache_table->print();
+ tty->cr();
}
void SystemDictionary::verify() {
- guarantee(dictionary() != NULL, "Verify of system dictionary failed");
guarantee(constraints() != NULL,
"Verify of loader constraints failed");
- guarantee(dictionary()->number_of_entries() >= 0 &&
- placeholders()->number_of_entries() >= 0,
- "Verify of system dictionary failed");
+ guarantee(placeholders()->number_of_entries() >= 0,
+ "Verify of placeholders failed");
+
+ GCMutexLocker mu(SystemDictionary_lock);
// Verify dictionary
- dictionary()->verify();
+ ClassLoaderDataGraph::verify_dictionary();
- GCMutexLocker mu(SystemDictionary_lock);
placeholders()->verify();
// Verify constraint table
guarantee(constraints() != NULL, "Verify of loader constraints failed");
- constraints()->verify(dictionary(), placeholders());
+ constraints()->verify(placeholders());
+
+ _pd_cache_table->verify();
}
// caller needs ResourceMark