8292218: Convert PackageEntryTable to ResourceHashtable
Reviewed-by: lfoltan, iklam, dholmes
This commit is contained in:
parent
871b7dab14
commit
9f8cc42135
@ -1011,25 +1011,9 @@ oop ClassLoader::get_system_package(const char* name, TRAPS) {
|
|||||||
objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
// List of pointers to PackageEntrys that have loaded classes.
|
// List of pointers to PackageEntrys that have loaded classes.
|
||||||
GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
|
PackageEntryTable* pe_table =
|
||||||
{
|
|
||||||
MutexLocker ml(THREAD, Module_lock);
|
|
||||||
|
|
||||||
PackageEntryTable* pe_table =
|
|
||||||
ClassLoaderData::the_null_class_loader_data()->packages();
|
ClassLoaderData::the_null_class_loader_data()->packages();
|
||||||
|
GrowableArray<PackageEntry*>* loaded_class_pkgs = pe_table->get_system_packages();
|
||||||
// Collect the packages that have at least one loaded class.
|
|
||||||
for (int x = 0; x < pe_table->table_size(); x++) {
|
|
||||||
for (PackageEntry* package_entry = pe_table->bucket(x);
|
|
||||||
package_entry != NULL;
|
|
||||||
package_entry = package_entry->next()) {
|
|
||||||
if (package_entry->has_loaded_class()) {
|
|
||||||
loaded_class_pkgs->append(package_entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Allocate objArray and fill with java.lang.String
|
// Allocate objArray and fill with java.lang.String
|
||||||
objArrayOop r = oopFactory::new_objArray(vmClasses::String_klass(),
|
objArrayOop r = oopFactory::new_objArray(vmClasses::String_klass(),
|
||||||
|
@ -163,7 +163,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool has_class_mirror_ho
|
|||||||
|
|
||||||
// A ClassLoaderData created solely for a non-strong hidden class should never
|
// A ClassLoaderData created solely for a non-strong hidden class should never
|
||||||
// have a ModuleEntryTable or PackageEntryTable created for it.
|
// have a ModuleEntryTable or PackageEntryTable created for it.
|
||||||
_packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
|
_packages = new PackageEntryTable();
|
||||||
if (h_class_loader.is_null()) {
|
if (h_class_loader.is_null()) {
|
||||||
// Create unnamed module for boot loader
|
// Create unnamed module for boot loader
|
||||||
_unnamed_module = ModuleEntry::create_boot_unnamed_module(this);
|
_unnamed_module = ModuleEntry::create_boot_unnamed_module(this);
|
||||||
@ -407,13 +407,7 @@ void ClassLoaderData::modules_do(void f(ModuleEntry*)) {
|
|||||||
void ClassLoaderData::packages_do(void f(PackageEntry*)) {
|
void ClassLoaderData::packages_do(void f(PackageEntry*)) {
|
||||||
assert_locked_or_safepoint(Module_lock);
|
assert_locked_or_safepoint(Module_lock);
|
||||||
if (_packages != NULL) {
|
if (_packages != NULL) {
|
||||||
for (int i = 0; i < _packages->table_size(); i++) {
|
_packages->packages_do(f);
|
||||||
for (PackageEntry* entry = _packages->bucket(i);
|
|
||||||
entry != NULL;
|
|
||||||
entry = entry->next()) {
|
|
||||||
f(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,21 +353,21 @@ ModuleEntry* ModuleEntry::new_unnamed_module_entry(Handle module_handle, ClassLo
|
|||||||
|
|
||||||
ModuleEntryTable::ModuleEntryTable() { }
|
ModuleEntryTable::ModuleEntryTable() { }
|
||||||
|
|
||||||
class ModuleEntryTableDeleter : public StackObj {
|
|
||||||
public:
|
|
||||||
bool do_entry(const Symbol*& name, ModuleEntry*& entry) {
|
|
||||||
if (log_is_enabled(Info, module, unload) || log_is_enabled(Debug, module)) {
|
|
||||||
ResourceMark rm;
|
|
||||||
const char* str = name->as_C_string();
|
|
||||||
log_info(module, unload)("unloading module %s", str);
|
|
||||||
log_debug(module)("ModuleEntryTable: deleting module: %s", str);
|
|
||||||
}
|
|
||||||
delete entry;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ModuleEntryTable::~ModuleEntryTable() {
|
ModuleEntryTable::~ModuleEntryTable() {
|
||||||
|
class ModuleEntryTableDeleter : public StackObj {
|
||||||
|
public:
|
||||||
|
bool do_entry(const Symbol*& name, ModuleEntry*& entry) {
|
||||||
|
if (log_is_enabled(Info, module, unload) || log_is_enabled(Debug, module)) {
|
||||||
|
ResourceMark rm;
|
||||||
|
const char* str = name->as_C_string();
|
||||||
|
log_info(module, unload)("unloading module %s", str);
|
||||||
|
log_debug(module)("ModuleEntryTable: deleting module: %s", str);
|
||||||
|
}
|
||||||
|
delete entry;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ModuleEntryTableDeleter deleter;
|
ModuleEntryTableDeleter deleter;
|
||||||
_table.unlink(&deleter);
|
_table.unlink(&deleter);
|
||||||
assert(_table.number_of_entries() == 0, "should have removed all entries");
|
assert(_table.number_of_entries() == 0, "should have removed all entries");
|
||||||
|
@ -214,8 +214,8 @@ static void define_javabase_module(Handle module_handle, jstring version, jstrin
|
|||||||
// loop through and add any new packages for java.base
|
// loop through and add any new packages for java.base
|
||||||
for (int x = 0; x < pkg_list->length(); x++) {
|
for (int x = 0; x < pkg_list->length(); x++) {
|
||||||
// Some of java.base's packages were added early in bootstrapping, ignore duplicates.
|
// Some of java.base's packages were added early in bootstrapping, ignore duplicates.
|
||||||
package_table->locked_create_entry_if_not_exist(pkg_list->at(x),
|
package_table->locked_create_entry_if_absent(pkg_list->at(x),
|
||||||
ModuleEntryTable::javabase_moduleEntry());
|
ModuleEntryTable::javabase_moduleEntry());
|
||||||
assert(package_table->locked_lookup_only(pkg_list->at(x)) != NULL,
|
assert(package_table->locked_lookup_only(pkg_list->at(x)) != NULL,
|
||||||
"Unable to create a " JAVA_BASE_NAME " package entry");
|
"Unable to create a " JAVA_BASE_NAME " package entry");
|
||||||
// Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of
|
// Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2022, 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,11 +37,30 @@
|
|||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "utilities/events.hpp"
|
#include "utilities/events.hpp"
|
||||||
#include "utilities/growableArray.hpp"
|
#include "utilities/growableArray.hpp"
|
||||||
#include "utilities/hashtable.inline.hpp"
|
|
||||||
#include "utilities/ostream.hpp"
|
#include "utilities/ostream.hpp"
|
||||||
#include "utilities/quickSort.hpp"
|
#include "utilities/quickSort.hpp"
|
||||||
#include "utilities/resourceHash.hpp"
|
#include "utilities/resourceHash.hpp"
|
||||||
|
|
||||||
|
PackageEntry::PackageEntry(Symbol* name, ModuleEntry* module) :
|
||||||
|
_name(name),
|
||||||
|
_module(module),
|
||||||
|
_export_flags(0),
|
||||||
|
_classpath_index(-1),
|
||||||
|
_must_walk_exports(false),
|
||||||
|
_qualified_exports(NULL),
|
||||||
|
_defined_by_cds_in_class_path(0)
|
||||||
|
{
|
||||||
|
// name can't be null
|
||||||
|
_name->increment_refcount();
|
||||||
|
|
||||||
|
JFR_ONLY(INIT_ID(this);)
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageEntry::~PackageEntry() {
|
||||||
|
delete_qualified_exports();
|
||||||
|
_name->decrement_refcount();
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if this package specifies m as a qualified export, including through an unnamed export
|
// Returns true if this package specifies m as a qualified export, including through an unnamed export
|
||||||
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
|
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
|
||||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||||
@ -169,28 +188,26 @@ void PackageEntry::delete_qualified_exports() {
|
|||||||
_qualified_exports = NULL;
|
_qualified_exports = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageEntryTable::PackageEntryTable(int table_size)
|
PackageEntryTable::PackageEntryTable() { }
|
||||||
: Hashtable<Symbol*, mtModule>(table_size, sizeof(PackageEntry))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageEntryTable::~PackageEntryTable() {
|
PackageEntryTable::~PackageEntryTable() {
|
||||||
// Walk through all buckets and all entries in each bucket,
|
class PackageEntryTableDeleter : public StackObj {
|
||||||
// freeing each entry.
|
public:
|
||||||
for (int i = 0; i < table_size(); ++i) {
|
bool do_entry(const Symbol*& name, PackageEntry*& entry) {
|
||||||
for (PackageEntry* p = bucket(i); p != NULL;) {
|
if (log_is_enabled(Info, module, unload) || log_is_enabled(Debug, module)) {
|
||||||
PackageEntry* to_remove = p;
|
ResourceMark rm;
|
||||||
// read next before freeing.
|
const char* str = name->as_C_string();
|
||||||
p = p->next();
|
log_info(module, unload)("unloading package %s", str);
|
||||||
|
log_debug(module)("PackageEntry: deleting package: %s", str);
|
||||||
// Clean out the C heap allocated qualified exports list first before freeing the entry
|
}
|
||||||
to_remove->delete_qualified_exports();
|
delete entry;
|
||||||
to_remove->name()->decrement_refcount();
|
return true;
|
||||||
|
|
||||||
BasicHashtable<mtModule>::free_entry(to_remove);
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
assert(number_of_entries() == 0, "should have removed all entries");
|
|
||||||
|
PackageEntryTableDeleter deleter;
|
||||||
|
_table.unlink(&deleter);
|
||||||
|
assert(_table.number_of_entries() == 0, "should have removed all entries");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
@ -225,21 +242,19 @@ PackageEntry* PackageEntry::get_archived_entry(PackageEntry* orig_entry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PackageEntry::iterate_symbols(MetaspaceClosure* closure) {
|
void PackageEntry::iterate_symbols(MetaspaceClosure* closure) {
|
||||||
closure->push(literal_addr()); // name
|
closure->push(&_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackageEntry::init_as_archived_entry() {
|
void PackageEntry::init_as_archived_entry() {
|
||||||
Array<ModuleEntry*>* archived_qualified_exports = ModuleEntry::write_growable_array(_qualified_exports);
|
Array<ModuleEntry*>* archived_qualified_exports = ModuleEntry::write_growable_array(_qualified_exports);
|
||||||
|
|
||||||
set_next(NULL);
|
_name = ArchiveBuilder::get_relocated_symbol(_name);
|
||||||
set_literal(ArchiveBuilder::get_relocated_symbol(literal()));
|
|
||||||
set_hash(0x0); // re-init at runtime
|
|
||||||
_module = ModuleEntry::get_archived_entry(_module);
|
_module = ModuleEntry::get_archived_entry(_module);
|
||||||
_qualified_exports = (GrowableArray<ModuleEntry*>*)archived_qualified_exports;
|
_qualified_exports = (GrowableArray<ModuleEntry*>*)archived_qualified_exports;
|
||||||
_defined_by_cds_in_class_path = 0;
|
_defined_by_cds_in_class_path = 0;
|
||||||
JFR_ONLY(set_trace_id(0)); // re-init at runtime
|
JFR_ONLY(set_trace_id(0)); // re-init at runtime
|
||||||
|
|
||||||
ArchivePtrMarker::mark_pointer((address*)literal_addr());
|
ArchivePtrMarker::mark_pointer((address*)&_name);
|
||||||
ArchivePtrMarker::mark_pointer((address*)&_module);
|
ArchivePtrMarker::mark_pointer((address*)&_module);
|
||||||
ArchivePtrMarker::mark_pointer((address*)&_qualified_exports);
|
ArchivePtrMarker::mark_pointer((address*)&_qualified_exports);
|
||||||
}
|
}
|
||||||
@ -255,38 +270,38 @@ static int compare_package_by_name(PackageEntry* a, PackageEntry* b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PackageEntryTable::iterate_symbols(MetaspaceClosure* closure) {
|
void PackageEntryTable::iterate_symbols(MetaspaceClosure* closure) {
|
||||||
for (int i = 0; i < table_size(); ++i) {
|
auto syms = [&] (const Symbol*& key, PackageEntry*& p) {
|
||||||
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
|
|
||||||
p->iterate_symbols(closure);
|
p->iterate_symbols(closure);
|
||||||
}
|
};
|
||||||
}
|
_table.iterate_all(syms);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array<PackageEntry*>* PackageEntryTable::allocate_archived_entries() {
|
Array<PackageEntry*>* PackageEntryTable::allocate_archived_entries() {
|
||||||
// First count the packages in named modules
|
// First count the packages in named modules
|
||||||
int n, i;
|
int n = 0;
|
||||||
for (n = 0, i = 0; i < table_size(); ++i) {
|
auto count = [&] (const Symbol*& key, PackageEntry*& p) {
|
||||||
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
|
if (p->module()->is_named()) {
|
||||||
if (p->module()->name() != NULL) {
|
n++;
|
||||||
n++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
_table.iterate_all(count);
|
||||||
|
|
||||||
Array<PackageEntry*>* archived_packages = ArchiveBuilder::new_rw_array<PackageEntry*>(n);
|
Array<PackageEntry*>* archived_packages = ArchiveBuilder::new_rw_array<PackageEntry*>(n);
|
||||||
for (n = 0, i = 0; i < table_size(); ++i) {
|
// reset n
|
||||||
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
|
n = 0;
|
||||||
if (p->module()->name() != NULL) {
|
auto grab = [&] (const Symbol*& key, PackageEntry*& p) {
|
||||||
// We don't archive unnamed modules, or packages in unnamed modules. They will be
|
if (p->module()->is_named()) {
|
||||||
// created on-demand at runtime as classes in such packages are loaded.
|
// We don't archive unnamed modules, or packages in unnamed modules. They will be
|
||||||
archived_packages->at_put(n++, p);
|
// created on-demand at runtime as classes in such packages are loaded.
|
||||||
}
|
archived_packages->at_put(n++, p);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
_table.iterate_all(grab);
|
||||||
|
|
||||||
if (n > 1) {
|
if (n > 1) {
|
||||||
QuickSort::sort(archived_packages->data(), n, (_sort_Fn)compare_package_by_name, true);
|
QuickSort::sort(archived_packages->data(), n, (_sort_Fn)compare_package_by_name, true);
|
||||||
}
|
}
|
||||||
for (i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
archived_packages->at_put(i, archived_packages->at(i)->allocate_archived_entry());
|
archived_packages->at_put(i, archived_packages->at(i)->allocate_archived_entry());
|
||||||
ArchivePtrMarker::mark_pointer((address*)archived_packages->adr_at(i));
|
ArchivePtrMarker::mark_pointer((address*)archived_packages->adr_at(i));
|
||||||
}
|
}
|
||||||
@ -306,63 +321,41 @@ void PackageEntryTable::load_archived_entries(Array<PackageEntry*>* archived_pac
|
|||||||
for (int i = 0; i < archived_packages->length(); i++) {
|
for (int i = 0; i < archived_packages->length(); i++) {
|
||||||
PackageEntry* archived_entry = archived_packages->at(i);
|
PackageEntry* archived_entry = archived_packages->at(i);
|
||||||
archived_entry->load_from_archive();
|
archived_entry->load_from_archive();
|
||||||
|
_table.put(archived_entry->name(), archived_entry);
|
||||||
unsigned int hash = compute_hash(archived_entry->name());
|
|
||||||
archived_entry->set_hash(hash);
|
|
||||||
add_entry(hash_to_index(hash), archived_entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
||||||
PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
|
|
||||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
|
||||||
PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::new_entry(hash, name);
|
|
||||||
|
|
||||||
JFR_ONLY(INIT_ID(entry);)
|
|
||||||
|
|
||||||
// Initialize fields specific to a PackageEntry
|
|
||||||
entry->init();
|
|
||||||
entry->name()->increment_refcount();
|
|
||||||
entry->set_module(module);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageEntryTable::add_entry(int index, PackageEntry* new_entry) {
|
|
||||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
|
||||||
Hashtable<Symbol*, mtModule>::add_entry(index, (HashtableEntry<Symbol*, mtModule>*)new_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create package entry in loader's package entry table. Assume Module lock
|
// Create package entry in loader's package entry table. Assume Module lock
|
||||||
// was taken by caller.
|
// was taken by caller.
|
||||||
void PackageEntryTable::locked_create_entry(Symbol* name, ModuleEntry* module) {
|
void PackageEntryTable::locked_create_entry(Symbol* name, ModuleEntry* module) {
|
||||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||||
assert(locked_lookup_only(name) == NULL, "Package entry already exists");
|
assert(locked_lookup_only(name) == NULL, "Package entry already exists");
|
||||||
PackageEntry* entry = new_entry(compute_hash(name), name, module);
|
PackageEntry* entry = new PackageEntry(name, module);
|
||||||
add_entry(index_for(name), entry);
|
bool created = _table.put(name, entry);
|
||||||
|
assert(created, "must be");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create package entry in loader's package entry table if it does not already
|
// Create package entry in loader's package entry table if it does not already
|
||||||
// exist. Assume Module lock was taken by caller.
|
// exist. Assume Module lock was taken by caller.
|
||||||
void PackageEntryTable::locked_create_entry_if_not_exist(Symbol* name, ModuleEntry* module) {
|
PackageEntry* PackageEntryTable::locked_create_entry_if_absent(Symbol* name, ModuleEntry* module) {
|
||||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||||
// Check if package entry already exists. If not, create it.
|
// Check if package entry already exists. If not, create it.
|
||||||
if (locked_lookup_only(name) == NULL) {
|
bool created;
|
||||||
locked_create_entry(name, module);
|
PackageEntry* entry = new PackageEntry(name, module);
|
||||||
|
PackageEntry** old_entry = _table.put_if_absent(name, entry, &created);
|
||||||
|
if (created) {
|
||||||
|
return entry;
|
||||||
|
} else {
|
||||||
|
delete entry;
|
||||||
|
return *old_entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageEntry* PackageEntryTable::lookup(Symbol* name, ModuleEntry* module) {
|
PackageEntry* PackageEntryTable::create_entry_if_absent(Symbol* name, ModuleEntry* module) {
|
||||||
MutexLocker ml(Module_lock);
|
MutexLocker ml(Module_lock);
|
||||||
PackageEntry* p = locked_lookup_only(name);
|
return locked_create_entry_if_absent(name, module);
|
||||||
if (p != NULL) {
|
|
||||||
return p;
|
|
||||||
} else {
|
|
||||||
assert(module != NULL, "module should never be null");
|
|
||||||
PackageEntry* entry = new_entry(compute_hash(name), name, module);
|
|
||||||
add_entry(index_for(name), entry);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
|
PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
|
||||||
@ -373,33 +366,26 @@ PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
|
|||||||
|
|
||||||
PackageEntry* PackageEntryTable::locked_lookup_only(Symbol* name) {
|
PackageEntry* PackageEntryTable::locked_lookup_only(Symbol* name) {
|
||||||
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
assert(Module_lock->owned_by_self(), "should have the Module_lock");
|
||||||
int index = index_for(name);
|
PackageEntry** entry = _table.get(name);
|
||||||
for (PackageEntry* p = bucket(index); p != NULL; p = p->next()) {
|
return entry == nullptr ? nullptr : *entry;
|
||||||
if (p->name()->fast_compare(name) == 0) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when a define module for java.base is being processed.
|
// Called when a define module for java.base is being processed.
|
||||||
// Verify the packages loaded thus far are in java.base's package list.
|
// Verify the packages loaded thus far are in java.base's package list.
|
||||||
void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
|
void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
|
||||||
assert_lock_strong(Module_lock);
|
assert_lock_strong(Module_lock);
|
||||||
for (int i = 0; i < table_size(); i++) {
|
auto verifier = [&] (const Symbol*& name, PackageEntry*& entry) {
|
||||||
for (PackageEntry* entry = bucket(i);
|
ModuleEntry* m = entry->module();
|
||||||
entry != NULL;
|
Symbol* module_name = (m == NULL ? NULL : m->name());
|
||||||
entry = entry->next()) {
|
if (module_name != NULL &&
|
||||||
ModuleEntry* m = entry->module();
|
(module_name->fast_compare(vmSymbols::java_base()) == 0) &&
|
||||||
Symbol* module_name = (m == NULL ? NULL : m->name());
|
!pkg_list->contains(entry->name())) {
|
||||||
if (module_name != NULL &&
|
ResourceMark rm;
|
||||||
(module_name->fast_compare(vmSymbols::java_base()) == 0) &&
|
vm_exit_during_initialization("A non-" JAVA_BASE_NAME " package was loaded prior to module system initialization",
|
||||||
!pkg_list->contains(entry->name())) {
|
entry->name()->as_C_string());
|
||||||
ResourceMark rm;
|
|
||||||
vm_exit_during_initialization("A non-" JAVA_BASE_NAME " package was loaded prior to module system initialization", entry->name()->as_C_string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
_table.iterate_all(verifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// iteration of qualified exports
|
// iteration of qualified exports
|
||||||
@ -424,31 +410,48 @@ bool PackageEntry::exported_pending_delete() const {
|
|||||||
// Remove dead entries from all packages' exported list
|
// Remove dead entries from all packages' exported list
|
||||||
void PackageEntryTable::purge_all_package_exports() {
|
void PackageEntryTable::purge_all_package_exports() {
|
||||||
assert_locked_or_safepoint(Module_lock);
|
assert_locked_or_safepoint(Module_lock);
|
||||||
for (int i = 0; i < table_size(); i++) {
|
auto purge = [&] (const Symbol*& name, PackageEntry*& entry) {
|
||||||
for (PackageEntry* entry = bucket(i);
|
if (entry->exported_pending_delete()) {
|
||||||
entry != NULL;
|
// exported list is pending deletion due to a transition
|
||||||
entry = entry->next()) {
|
// from qualified to unqualified
|
||||||
if (entry->exported_pending_delete()) {
|
entry->delete_qualified_exports();
|
||||||
// exported list is pending deletion due to a transition
|
} else if (entry->is_qual_exported()) {
|
||||||
// from qualified to unqualified
|
entry->purge_qualified_exports();
|
||||||
entry->delete_qualified_exports();
|
|
||||||
} else if (entry->is_qual_exported()) {
|
|
||||||
entry->purge_qualified_exports();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
_table.iterate_all(purge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageEntryTable::packages_do(void f(PackageEntry*)) {
|
||||||
|
auto doit = [&] (const Symbol*&name, PackageEntry*& entry) {
|
||||||
|
f(entry);
|
||||||
|
};
|
||||||
|
assert_locked_or_safepoint(Module_lock);
|
||||||
|
_table.iterate_all(doit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GrowableArray<PackageEntry*>* PackageEntryTable::get_system_packages() {
|
||||||
|
GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
|
||||||
|
auto grab = [&] (const Symbol*&name, PackageEntry*& entry) {
|
||||||
|
if (entry->has_loaded_class()) {
|
||||||
|
loaded_class_pkgs->append(entry);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MutexLocker ml(Module_lock);
|
||||||
|
_table.iterate_all(grab);
|
||||||
|
// Returns a resource allocated object so caller must have ResourceMark
|
||||||
|
return loaded_class_pkgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackageEntryTable::print(outputStream* st) {
|
void PackageEntryTable::print(outputStream* st) {
|
||||||
|
auto printer = [&] (const Symbol*& name, PackageEntry*& entry) {
|
||||||
|
entry->print(st);
|
||||||
|
};
|
||||||
st->print_cr("Package Entry Table (table_size=%d, entries=%d)",
|
st->print_cr("Package Entry Table (table_size=%d, entries=%d)",
|
||||||
table_size(), number_of_entries());
|
_table.table_size(), _table.number_of_entries());
|
||||||
for (int i = 0; i < table_size(); i++) {
|
_table.iterate_all(printer);
|
||||||
for (PackageEntry* probe = bucket(i);
|
|
||||||
probe != NULL;
|
|
||||||
probe = probe->next()) {
|
|
||||||
probe->print(st);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function may be called from debuggers so access private fields directly
|
// This function may be called from debuggers so access private fields directly
|
||||||
@ -457,17 +460,9 @@ void PackageEntryTable::print(outputStream* st) {
|
|||||||
void PackageEntry::print(outputStream* st) {
|
void PackageEntry::print(outputStream* st) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
|
st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
|
||||||
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next " PTR_FORMAT,
|
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d ",
|
||||||
p2i(this), name()->as_C_string(),
|
p2i(this), name()->as_C_string(),
|
||||||
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
|
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
|
||||||
_classpath_index, _export_flags == PKG_EXP_UNQUALIFIED,
|
_classpath_index, _export_flags == PKG_EXP_UNQUALIFIED,
|
||||||
_export_flags == PKG_EXP_ALLUNNAMED, p2i(next()));
|
_export_flags == PKG_EXP_ALLUNNAMED);
|
||||||
}
|
|
||||||
|
|
||||||
void PackageEntryTable::verify() {
|
|
||||||
verify_table<PackageEntry>("Package Entry Table");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageEntry::verify() {
|
|
||||||
guarantee(name() != NULL, "A package entry must have a corresponding symbol name.");
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2022, 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
|
||||||
@ -29,7 +29,7 @@
|
|||||||
#include "oops/symbol.hpp"
|
#include "oops/symbol.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
#include "utilities/growableArray.hpp"
|
#include "utilities/growableArray.hpp"
|
||||||
#include "utilities/hashtable.hpp"
|
#include "utilities/resourceHash.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "utilities/ostream.hpp"
|
#include "utilities/ostream.hpp"
|
||||||
#if INCLUDE_JFR
|
#if INCLUDE_JFR
|
||||||
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
template <class T> class Array;
|
template <class T> class Array;
|
||||||
class MetaspaceClosure;
|
class MetaspaceClosure;
|
||||||
|
class ModuleEntry;
|
||||||
|
|
||||||
// A PackageEntry basically represents a Java package. It contains:
|
// A PackageEntry basically represents a Java package. It contains:
|
||||||
// - Symbol* containing the package's name.
|
// - Symbol* containing the package's name.
|
||||||
@ -97,8 +98,9 @@ class MetaspaceClosure;
|
|||||||
#define PKG_EXP_ALLUNNAMED 0x0002
|
#define PKG_EXP_ALLUNNAMED 0x0002
|
||||||
#define PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED (PKG_EXP_UNQUALIFIED | PKG_EXP_ALLUNNAMED)
|
#define PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED (PKG_EXP_UNQUALIFIED | PKG_EXP_ALLUNNAMED)
|
||||||
|
|
||||||
class PackageEntry : public HashtableEntry<Symbol*, mtModule> {
|
class PackageEntry : public CHeapObj<mtModule> {
|
||||||
private:
|
private:
|
||||||
|
Symbol* _name;
|
||||||
ModuleEntry* _module;
|
ModuleEntry* _module;
|
||||||
// Indicates if package is exported unqualifiedly or to all unnamed. Access to
|
// Indicates if package is exported unqualifiedly or to all unnamed. Access to
|
||||||
// this field is protected by the Module_lock.
|
// this field is protected by the Module_lock.
|
||||||
@ -120,17 +122,11 @@ private:
|
|||||||
// a bit map indicating which CDS classpath entries have defined classes in this package.
|
// a bit map indicating which CDS classpath entries have defined classes in this package.
|
||||||
volatile int _defined_by_cds_in_class_path;
|
volatile int _defined_by_cds_in_class_path;
|
||||||
public:
|
public:
|
||||||
void init() {
|
PackageEntry(Symbol* name, ModuleEntry* module);
|
||||||
_module = NULL;
|
~PackageEntry();
|
||||||
_export_flags = 0;
|
|
||||||
_classpath_index = -1;
|
|
||||||
_must_walk_exports = false;
|
|
||||||
_qualified_exports = NULL;
|
|
||||||
_defined_by_cds_in_class_path = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// package name
|
// package name
|
||||||
Symbol* name() const { return literal(); }
|
Symbol* name() const { return _name; }
|
||||||
|
|
||||||
// the module containing the package definition
|
// the module containing the package definition
|
||||||
ModuleEntry* module() const { return _module; }
|
ModuleEntry* module() const { return _module; }
|
||||||
@ -199,14 +195,6 @@ public:
|
|||||||
void add_qexport(ModuleEntry* m);
|
void add_qexport(ModuleEntry* m);
|
||||||
void set_export_walk_required(ClassLoaderData* m_loader_data);
|
void set_export_walk_required(ClassLoaderData* m_loader_data);
|
||||||
|
|
||||||
PackageEntry* next() const {
|
|
||||||
return (PackageEntry*)HashtableEntry<Symbol*, mtModule>::next();
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageEntry** next_addr() {
|
|
||||||
return (PackageEntry**)HashtableEntry<Symbol*, mtModule>::next_addr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// iteration of qualified exports
|
// iteration of qualified exports
|
||||||
void package_exports_do(ModuleClosure* f);
|
void package_exports_do(ModuleClosure* f);
|
||||||
|
|
||||||
@ -217,7 +205,6 @@ public:
|
|||||||
void delete_qualified_exports();
|
void delete_qualified_exports();
|
||||||
|
|
||||||
void print(outputStream* st = tty);
|
void print(outputStream* st = tty);
|
||||||
void verify();
|
|
||||||
|
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
void iterate_symbols(MetaspaceClosure* closure);
|
void iterate_symbols(MetaspaceClosure* closure);
|
||||||
@ -248,47 +235,24 @@ public:
|
|||||||
|
|
||||||
// The PackageEntryTable is a Hashtable containing a list of all packages defined
|
// The PackageEntryTable is a Hashtable containing a list of all packages defined
|
||||||
// by a particular class loader. Each package is represented as a PackageEntry node.
|
// by a particular class loader. Each package is represented as a PackageEntry node.
|
||||||
// The PackageEntryTable's lookup is lock free.
|
class PackageEntryTable : public CHeapObj<mtModule> {
|
||||||
//
|
ResourceHashtable<const Symbol*, PackageEntry*, 109, ResourceObj::C_HEAP, mtModule,
|
||||||
class PackageEntryTable : public Hashtable<Symbol*, mtModule> {
|
Symbol::compute_hash> _table;
|
||||||
friend class VMStructs;
|
|
||||||
public:
|
public:
|
||||||
enum Constants {
|
PackageEntryTable();
|
||||||
_packagetable_entry_size = 109 // number of entries in package entry table
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
PackageEntry* new_entry(unsigned int hash, Symbol* name, ModuleEntry* module);
|
|
||||||
void add_entry(int index, PackageEntry* new_entry);
|
|
||||||
|
|
||||||
int entry_size() const { return BasicHashtable<mtModule>::entry_size(); }
|
|
||||||
|
|
||||||
PackageEntry** bucket_addr(int i) {
|
|
||||||
return (PackageEntry**)Hashtable<Symbol*, mtModule>::bucket_addr(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int compute_hash(Symbol* name) { return (unsigned int)(name->identity_hash()); }
|
|
||||||
int index_for(Symbol* name) const { return hash_to_index(compute_hash(name)); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
PackageEntryTable(int table_size);
|
|
||||||
~PackageEntryTable();
|
~PackageEntryTable();
|
||||||
|
|
||||||
PackageEntry* bucket(int i) {
|
|
||||||
return (PackageEntry*)Hashtable<Symbol*, mtModule>::bucket(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create package entry in loader's package entry table. Assume Module
|
// Create package entry in loader's package entry table. Assume Module
|
||||||
// lock was taken by caller.
|
// lock was taken by caller.
|
||||||
void locked_create_entry(Symbol* name, ModuleEntry* module);
|
void locked_create_entry(Symbol* name, ModuleEntry* module);
|
||||||
|
|
||||||
// Create package entry in loader's package entry table if it does not
|
// Create package entry in loader's package entry table if it does not
|
||||||
// already exist. Assume Module lock was taken by caller.
|
// already exist. Assume Module lock was taken by caller.
|
||||||
void locked_create_entry_if_not_exist(Symbol* name, ModuleEntry* module);
|
PackageEntry* locked_create_entry_if_absent(Symbol* name, ModuleEntry* module);
|
||||||
|
|
||||||
// Lookup Package with loader's package entry table, add it if not found.
|
// Lookup Package with loader's package entry table, add it if not found.
|
||||||
// This will acquire the Module lock.
|
// This will acquire the Module lock.
|
||||||
PackageEntry* lookup(Symbol* name, ModuleEntry* module);
|
PackageEntry* create_entry_if_absent(Symbol* name, ModuleEntry* module);
|
||||||
|
|
||||||
// Only lookup Package within loader's package entry table.
|
// Only lookup Package within loader's package entry table.
|
||||||
// This will acquire the Module lock.
|
// This will acquire the Module lock.
|
||||||
@ -303,8 +267,11 @@ public:
|
|||||||
// purge dead weak references out of exported list
|
// purge dead weak references out of exported list
|
||||||
void purge_all_package_exports();
|
void purge_all_package_exports();
|
||||||
|
|
||||||
|
GrowableArray<PackageEntry*>* get_system_packages();
|
||||||
|
|
||||||
|
void packages_do(void f(PackageEntry*));
|
||||||
|
|
||||||
void print(outputStream* st = tty);
|
void print(outputStream* st = tty);
|
||||||
void verify();
|
|
||||||
|
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
void iterate_symbols(MetaspaceClosure* closure);
|
void iterate_symbols(MetaspaceClosure* closure);
|
||||||
|
@ -2879,11 +2879,10 @@ void InstanceKlass::set_package(ClassLoaderData* loader_data, PackageEntry* pkg_
|
|||||||
// in the java.base module it will be caught later when java.base
|
// in the java.base module it will be caught later when java.base
|
||||||
// is defined by ModuleEntryTable::verify_javabase_packages check.
|
// is defined by ModuleEntryTable::verify_javabase_packages check.
|
||||||
assert(ModuleEntryTable::javabase_moduleEntry() != NULL, JAVA_BASE_NAME " module is NULL");
|
assert(ModuleEntryTable::javabase_moduleEntry() != NULL, JAVA_BASE_NAME " module is NULL");
|
||||||
_package_entry = loader_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_moduleEntry());
|
_package_entry = loader_data->packages()->create_entry_if_absent(pkg_name, ModuleEntryTable::javabase_moduleEntry());
|
||||||
} else {
|
} else {
|
||||||
assert(loader_data->unnamed_module() != NULL, "unnamed module is NULL");
|
assert(loader_data->unnamed_module() != NULL, "unnamed module is NULL");
|
||||||
_package_entry = loader_data->packages()->lookup(pkg_name,
|
_package_entry = loader_data->packages()->create_entry_if_absent(pkg_name, loader_data->unnamed_module());
|
||||||
loader_data->unnamed_module());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A package should have been successfully created
|
// A package should have been successfully created
|
||||||
|
@ -283,6 +283,5 @@ template class BasicHashtable<mtServiceability>;
|
|||||||
template class BasicHashtable<mtLogging>;
|
template class BasicHashtable<mtLogging>;
|
||||||
|
|
||||||
template void BasicHashtable<mtClass>::verify_table<DictionaryEntry>(char const*);
|
template void BasicHashtable<mtClass>::verify_table<DictionaryEntry>(char const*);
|
||||||
template void BasicHashtable<mtModule>::verify_table<PackageEntry>(char const*);
|
|
||||||
template void BasicHashtable<mtClass>::verify_table<ProtectionDomainCacheEntry>(char const*);
|
template void BasicHashtable<mtClass>::verify_table<ProtectionDomainCacheEntry>(char const*);
|
||||||
template void BasicHashtable<mtClass>::verify_table<PlaceholderEntry>(char const*);
|
template void BasicHashtable<mtClass>::verify_table<PlaceholderEntry>(char const*);
|
||||||
|
Loading…
Reference in New Issue
Block a user