< prev index next >
src/share/vm/classfile/systemDictionary.cpp
Print this page
@@ -33,10 +33,11 @@
#include "classfile/javaClasses.inline.hpp"
#include "classfile/klassFactory.hpp"
#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"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
@@ -85,23 +86,18 @@
#endif
#if INCLUDE_TRACE
#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]
= { NULL /*, NULL...*/ };
@@ -113,10 +109,14 @@
bool SystemDictionary::_has_checkPackageAccess = false;
// lazily initialized klass variables
InstanceKlass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL;
+// Default ProtectionDomainCacheSize value
+
+const int defaultProtectionDomainCacheSize = 1009;
+
// ----------------------------------------------------------------------------
// Java-level SystemLoader
oop SystemDictionary::java_system_loader() {
@@ -340,36 +340,36 @@
}
}
#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:
// if initial define, SD update will give LinkageError
// if redefine: compare_class_versions will give HIERARCHY_CHANGED
@@ -441,17 +441,22 @@
log->print(" protection domain: "); protection_domain()->print_value_on(log);
log->print(" loading: "); klass->print_value_on(log);
log->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);
if (HAS_PENDING_EXCEPTION) {
log_debug(protectiondomain)("DENIED !!!!!!!!!!!!!!!!!!!!!");
@@ -462,32 +467,21 @@
if (HAS_PENDING_EXCEPTION) return;
// 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,
+ dictionary->add_protection_domain(d_index, d_hash, klass,
protection_domain, THREAD);
}
- }
}
// We only get here if this thread finds that another thread
// has already claimed the placeholder token for the current operation,
// but that other thread either never owned or gave up the
@@ -544,13 +538,14 @@
InstanceKlass* SystemDictionary::handle_parallel_super_load(
Symbol* name, Symbol* superclassname, Handle class_loader,
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
// This code is reached in two situations. One if this thread
// is loading the same class twice (e.g. ClassCircularity, or
@@ -569,21 +564,21 @@
// parallelCapable class loaders do NOT wait for parallel superclass loads to complete
// Serial class loaders and bootstrap classloader do wait for superclass loads
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
// and spurious notifications
bool super_load_in_progress = true;
PlaceholderEntry* placeholder;
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;
} else {
placeholder = placeholders()->get_entry(p_index, p_hash, name, loader_data);
@@ -659,21 +654,21 @@
HandleMark hm(THREAD);
// 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
// This call uses find which checks protection domain already matches
// 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;
// Non-bootstrap class loaders will call out to class loader and
// define via jvm/jni_DefineClass which will acquire the
@@ -687,11 +682,11 @@
bool DoObjectLock = true;
if (is_parallelCapable(class_loader)) {
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.
// Make sure we are synchronized on the class loader before we proceed
Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
@@ -706,11 +701,11 @@
PlaceholderEntry* placeholder;
Symbol* superclassname = NULL;
{
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;
k = check;
} else {
@@ -790,11 +785,11 @@
// case 2: traditional with broken classloader lock. wait on first
// requestor.
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;
class_has_been_loaded = true;
}
@@ -815,11 +810,11 @@
// if they did not catch another thread holding LOAD_INSTANCE,
// need a check analogous to the acquire ObjectLocker/find_class
// 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;
class_has_been_loaded = true;
}
@@ -848,11 +843,11 @@
// Bootstrap goes through here to allow for an extra guarantee check
if (UnsyncloadClass || (class_loader.is_null())) {
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;
CLEAR_PENDING_EXCEPTION;
guarantee((!class_loader.is_null()), "dup definition for bootstrap loader?");
@@ -882,11 +877,11 @@
assert(thread->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_load((JavaThread *) thread, k);
}
}
}
- } // load_instance_class loop
+ } // load_instance_class
if (load_instance_added == true) {
// clean up placeholder entries for LOAD_INSTANCE success or error
// This brackets the SystemDictionary updates for both defining
// and initiating loaders
@@ -915,19 +910,11 @@
if (protection_domain() == NULL) return k;
// 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,
+ if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
protection_domain)) {
return k;
}
}
@@ -964,24 +951,15 @@
// If the ClassLoaderData has not been setup,
// then the class loader has no entries in the dictionary.
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);
}
// Look for a loaded instance or array klass by name. Do not do any loading.
// return NULL in case of error.
@@ -1031,11 +1009,10 @@
// Create a new CLD for anonymous class, that uses the same class loader
// as the host_klass
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());
}
assert(st != NULL, "invariant");
@@ -1062,11 +1039,11 @@
// Add to class hierarchy, initialize vtables, and do possible
// 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();
}
@@ -1185,22 +1162,23 @@
}
#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);
}
// If there is a shared dictionary, then find the entry for the
// given shared system class, if any.
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);
} else {
return NULL;
@@ -1622,12 +1600,13 @@
// Existing classloaders will call define_instance_class with the
// classloader lock held
// 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)
// Note we do this before updating the dictionary, as this can
// fail with an OutOfMemoryError (if it does, we will *not* put this
@@ -1641,11 +1620,11 @@
JavaCalls::call(&result, m, &args, CHECK);
}
// 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);
// Add to class hierarchy, initialize vtables, and do possible
@@ -1691,24 +1670,25 @@
InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader,
InstanceKlass* k, TRAPS) {
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;
{
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;
}
}
@@ -1726,11 +1706,11 @@
// caught by finding an entry in the SystemDictionary
if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instance_klass() != NULL)) {
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();
} else {
// This thread will define the class (even if earlier thread tried and had an error)
@@ -1765,10 +1745,11 @@
THROW_OOP_(linkage_exception(), NULL); // throws exception and returns
}
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()) {
return Handle(THREAD, _system_loader_lock_obj);
} else {
@@ -1802,50 +1783,43 @@
// ----------------------------------------------------------------------------
// Lookup
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);
}
// Basic find on classes in the midst of being loaded
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 ||
VerifyBeforeExit ||
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);
}
// ----------------------------------------------------------------------------
// Update hierachy. This is done before the new klass has been added to the SystemDictionary. The Recompile_lock
@@ -1868,46 +1842,23 @@
}
// ----------------------------------------------------------------------------
// 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 {
private:
BoolObjectClosure* _is_alive;
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:
VerifySDReachableAndLiveClosure(BoolObjectClosure* is_alive) : OopClosure(), _is_alive(is_alive) { }
@@ -1932,24 +1883,24 @@
do_cleaning);
}
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
}
if (do_cleaning) {
GCTraceTime(Debug, gc, phases) t("ResolvedMethodTable", gc_timer);
@@ -1962,12 +1913,20 @@
void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
strong->do_oop(&_java_system_loader);
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);
if (weak != NULL) {
@@ -1978,47 +1937,29 @@
void SystemDictionary::oops_do(OopClosure* f) {
f->do_oop(&_java_system_loader);
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);
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);
// Walk method handle intrinsics
invoke_method_table()->methods_do(f);
}
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();
}
// ----------------------------------------------------------------------------
// Lazily load klasses
@@ -2038,19 +1979,16 @@
// ----------------------------------------------------------------------------
// Initialization
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);
// Initialize basic classes
initialize_preloaded_classes(CHECK);
@@ -2197,13 +2135,13 @@
}
// 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,
InstanceKlass* k,
Handle class_loader, bool defining,
@@ -2214,16 +2152,16 @@
Symbol* name = k->name();
ClassLoaderData *loader_data = class_loader_data(class_loader);
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");
if ((defining == true) || (k != check)) {
linkage_error1 = "loader (instance of ";
@@ -2260,11 +2198,11 @@
THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
}
}
-// 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,
InstanceKlass* k,
Handle class_loader,
@@ -2295,22 +2233,23 @@
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);
+ // 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(name, loader_data, k);
+ dictionary->add_klass(d_index, d_hash, name, 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");
+ #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
+ #endif
SystemDictionary_lock->notify_all();
}
}
@@ -2376,23 +2315,23 @@
return true;
} else {
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);
+ Dictionary* dictionary1 = loader_data1->dictionary();
+ unsigned int d_hash1 = dictionary1->compute_hash(constraint_name);
+ int d_index1 = dictionary1->hash_to_index(d_hash1);
+
+ Dictionary* dictionary2 = loader_data2->dictionary();
+ unsigned int d_hash2 = dictionary2->compute_hash(constraint_name);
+ int d_index2 = dictionary2->hash_to_index(d_hash2);
+
{
MutexLocker mu_s(SystemDictionary_lock, THREAD);
-
- // Better never do a GC while we're holding these oops
- NoSafepointVerifier nosafepoint;
-
- InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, loader_data1);
- InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, loader_data2);
+ 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);
}
}
@@ -2840,68 +2779,76 @@
Handle mname(THREAD, (oop) result.get_jobject());
(*method_type_result) = method_type;
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);
+ }
- // Placeholders
GCMutexLocker mu(SystemDictionary_lock);
+
+ ClassLoaderDataGraph::print_dictionary(details);
+
+ // Placeholders
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");
// 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
const char* SystemDictionary::loader_name(const oop loader) {
return ((loader) == NULL ? "<bootloader>" :
< prev index next >