< prev index next >
src/share/vm/classfile/classLoaderData.cpp
Print this page
@@ -47,10 +47,11 @@
// the singleton class the_null_class_loader_data().
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
+#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/systemDictionary.hpp"
@@ -90,11 +91,11 @@
// An anonymous class loader data doesn't have anything to keep
// it from being unloaded during parsing of the anonymous class.
// The null-class-loader should always be kept alive.
_keep_alive((is_anonymous || h_class_loader.is_null()) ? 1 : 0),
_metaspace(NULL), _unloading(false), _klasses(NULL),
- _modules(NULL), _packages(NULL),
+ _modules(NULL), _packages(NULL), _dictionary(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(), _deallocate_list(NULL),
_next(NULL), _dependencies(dependencies),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
@@ -447,14 +448,81 @@
p2i((void *)k->class_loader()),
loader_name());
}
}
+// Class iterator used by the compiler. It gets some number of classes at
+// a safepoint to decay invocation counters on the methods.
+class ClassLoaderDataGraphKlassIteratorStatic {
+ ClassLoaderData* _current_loader_data = NULL;
+ Klass* _current_class_entry = NULL;
+ public:
+
+ InstanceKlass* try_get_next_class() {
+ assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
+ while (true) {
+
+ if (_current_class_entry != NULL) {
+ Klass* k = _current_class_entry;
+ _current_class_entry = _current_class_entry->next_link();
+
+ if (k->is_instance_klass()) {
+ InstanceKlass* ik = InstanceKlass::cast(k);
+ // Only return loaded classes
+ if (ik->is_loaded()) {
+ return ik;
+ }
+ }
+ } else {
+ // Go to next CLD
+ if (_current_loader_data != NULL) {
+ _current_loader_data = _current_loader_data->next();
+ }
+ // Start at the beginning
+ if (_current_loader_data == NULL) {
+ _current_loader_data = ClassLoaderDataGraph::_head;
+ }
+
+ _current_class_entry = _current_loader_data->klasses();
+ }
+ }
+ // never reached: an InstanceKlass should be returned above
+ }
+
+ // If the current class for the static iterator is a class being unloaded or
+ // deallocated, adjust the current class.
+ void adjust_saved_class(ClassLoaderData* cld) {
+ if (_current_loader_data == cld) {
+ _current_loader_data = cld->next();
+ if (_current_loader_data != NULL) {
+ _current_class_entry = _current_loader_data->klasses();
+ } // else try_get_next_class will start at the head
+ }
+ }
+
+ void adjust_saved_class(Klass* klass) {
+ if (_current_class_entry == klass) {
+ _current_class_entry = klass->next_link();
+ }
+ }
+};
+
+static ClassLoaderDataGraphKlassIteratorStatic static_klass_iterator;
+
+InstanceKlass* ClassLoaderDataGraph::try_get_next_class() {
+ return static_klass_iterator.try_get_next_class();
+}
+
+
// Remove a klass from the _klasses list for scratch_class during redefinition
// or parsed class in the case of an error.
void ClassLoaderData::remove_class(Klass* scratch_class) {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
+
+ // Adjust global class iterator.
+ static_klass_iterator.adjust_saved_class(scratch_class);
+
Klass* prev = NULL;
for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
if (k == scratch_class) {
if (prev == NULL) {
_klasses = k->next_link();
@@ -489,10 +557,13 @@
}
// In some rare cases items added to this list will not be freed elsewhere.
// To keep it simple, just free everything in it here.
free_deallocate_list();
+
+ // Clean up global class iterator for compiler
+ static_klass_iterator.adjust_saved_class(this);
}
ModuleEntryTable* ClassLoaderData::modules() {
// Lazily create the module entry table at first request.
// Lock-free access requires load_ptr_acquire.
@@ -511,10 +582,69 @@
}
}
return modules;
}
+const int _boot_loader_dictionary_size = 1009;
+const int _prime_array_size = 8; // array of primes for system dictionary size
+const int _average_depth_goal = 3; // goal for lookup length
+const int _primelist[_prime_array_size] = {107, 1009, 2017, 4049, 5051, 10103, 20201, 40423};
+
+// Calculate a "good" dictionary size based
+// on predicted or current loaded classes count *per class loader*
+// This size will be used for all class loaders if specified,
+// except boot loader and reflection class loaders
+static int calculate_dictionary_size(int classcount) {
+ static int newsize = 0; // only calculate once
+ if (newsize != 0) {
+ return newsize;
+ }
+ newsize = _primelist[0];
+ if (classcount > 0 && !DumpSharedSpaces) {
+ int index = 0;
+ int desiredsize = classcount/_average_depth_goal;
+ for (newsize = _primelist[index]; index < _prime_array_size -1;
+ newsize = _primelist[++index]) {
+ if (desiredsize <= newsize) {
+ break;
+ }
+ }
+ }
+ return newsize;
+}
+
+Dictionary* ClassLoaderData::dictionary_or_null() {
+ return load_ptr_acquire(&_dictionary);
+}
+
+Dictionary* ClassLoaderData::dictionary() {
+ assert(!is_anonymous(), "anonymous class loader data do not have a dictionary");
+ // Lazily create the dictionary, in the same way of lazily creating modules.
+ // Lock-free access requires load_ptr_acquire.
+ Dictionary* dictionary = load_ptr_acquire(&_dictionary);
+ if (dictionary == NULL) {
+ MutexLocker m1(SystemDictionary_lock);
+ // Check if _dictionary got allocated while we were waiting for this lock.
+ if ((dictionary = _dictionary) == NULL) {
+ int size;
+ if (this == the_null_class_loader_data()) {
+ size = _boot_loader_dictionary_size;
+ } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
+ size = 1; // there's only one class in relection class loader and no initiated classes
+ } else {
+ size = calculate_dictionary_size(PredictedLoadedClassCount);
+ }
+ dictionary = new Dictionary(this, size);
+ // Ensure _dictionary is stable, since it is examined without a lock.
+ // Don't need metaspace_lock since SystemDictionary_lock is held.
+ OrderAccess::release_store_ptr(&_dictionary, dictionary);
+ }
+ }
+ return dictionary;
+}
+
+// Unloading support
oop ClassLoaderData::keep_alive_object() const {
assert_locked_or_safepoint(_metaspace_lock);
assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
return is_anonymous() ? _klasses->java_mirror() : class_loader();
}
@@ -542,10 +672,17 @@
// Destroy the table itself
delete _modules;
_modules = NULL;
}
+ // Release C heap allocated hashtable for the dictionary
+ if (_dictionary != NULL) {
+ // Destroy the table itself
+ delete _dictionary;
+ _dictionary = NULL;
+ }
+
if (_unnamed_module != NULL) {
_unnamed_module->delete_unnamed_module();
_unnamed_module = NULL;
}
@@ -969,10 +1106,47 @@
assert(cld->is_unloading(), "invariant");
cld->classes_do(f);
}
}
+#define FOR_ALL_DICTIONARY(X) for (ClassLoaderData* X = _head; X != NULL; X = X->next()) \
+ if (X->dictionary_or_null() != NULL)
+
+// Walk classes in the loaded class dictionaries in various forms.
+void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->classes_do(f);
+ }
+}
+
+void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->classes_do(f, CHECK);
+ }
+}
+
+void ClassLoaderDataGraph::dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->all_entries_do(f);
+ }
+}
+
+void ClassLoaderDataGraph::verify_dictionary() {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->verify();
+ }
+}
+
+void ClassLoaderDataGraph::print_dictionary(bool details) {
+ FOR_ALL_DICTIONARY(cld) {
+ tty->print("Dictionary for class loader ");
+ cld->print_value();
+ tty->cr();
+ cld->dictionary()->print(details);
+ }
+}
+
GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
GrowableArray<ClassLoaderData*>* array = new GrowableArray<ClassLoaderData*>();
@@ -1069,18 +1243,21 @@
dead->set_next(_unloading);
_unloading = dead;
}
if (seen_dead_loader) {
- // Walk a ModuleEntry's reads and a PackageEntry's exports lists
- // to determine if there are modules on those lists that are now
+ // Walk a Dictionary, ModuleEntry's reads, and a PackageEntry's exports
+ // lists to determine if there are modules on those lists that are now
// dead and should be removed. A module's life cycle is equivalent
// to its defining class loader's life cycle. Since a module is
// considered dead if its class loader is dead, these walks must
// occur after each class loader's aliveness is determined.
data = _head;
while (data != NULL) {
+ if (data->dictionary_or_null() != NULL) {
+ data->dictionary()->do_unloading();
+ }
if (data->packages() != NULL) {
data->packages()->purge_all_package_exports();
}
if (data->modules_defined()) {
data->modules()->purge_all_module_reads();
@@ -1248,10 +1425,19 @@
out->print("class loader " INTPTR_FORMAT " ", p2i(this));
class_loader()->print_value_on(out);
}
}
+void ClassLoaderData::print_on(outputStream* out) const {
+ if (class_loader() == NULL) {
+ out->print("NULL class_loader");
+ } else {
+ out->print("class loader " INTPTR_FORMAT " ", p2i(this));
+ class_loader()->print_on(out);
+ }
+}
+
#if INCLUDE_TRACE
Ticks ClassLoaderDataGraph::_class_unload_time;
void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
< prev index next >