8292218: Convert PackageEntryTable to ResourceHashtable

Reviewed-by: lfoltan, iklam, dholmes
This commit is contained in:
Coleen Phillimore 2022-08-12 12:37:27 +00:00
parent 871b7dab14
commit 9f8cc42135
8 changed files with 168 additions and 230 deletions

View File

@ -1011,25 +1011,9 @@ oop ClassLoader::get_system_package(const char* name, TRAPS) {
objArrayOop ClassLoader::get_system_packages(TRAPS) {
ResourceMark rm(THREAD);
// List of pointers to PackageEntrys that have loaded classes.
GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
{
MutexLocker ml(THREAD, Module_lock);
PackageEntryTable* pe_table =
PackageEntryTable* pe_table =
ClassLoaderData::the_null_class_loader_data()->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);
}
}
}
}
GrowableArray<PackageEntry*>* loaded_class_pkgs = pe_table->get_system_packages();
// Allocate objArray and fill with java.lang.String
objArrayOop r = oopFactory::new_objArray(vmClasses::String_klass(),

View File

@ -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
// have a ModuleEntryTable or PackageEntryTable created for it.
_packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
_packages = new PackageEntryTable();
if (h_class_loader.is_null()) {
// Create unnamed module for boot loader
_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*)) {
assert_locked_or_safepoint(Module_lock);
if (_packages != NULL) {
for (int i = 0; i < _packages->table_size(); i++) {
for (PackageEntry* entry = _packages->bucket(i);
entry != NULL;
entry = entry->next()) {
f(entry);
}
}
_packages->packages_do(f);
}
}

View File

@ -353,21 +353,21 @@ ModuleEntry* ModuleEntry::new_unnamed_module_entry(Handle module_handle, ClassLo
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() {
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;
_table.unlink(&deleter);
assert(_table.number_of_entries() == 0, "should have removed all entries");

View File

@ -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
for (int x = 0; x < pkg_list->length(); x++) {
// 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),
ModuleEntryTable::javabase_moduleEntry());
package_table->locked_create_entry_if_absent(pkg_list->at(x),
ModuleEntryTable::javabase_moduleEntry());
assert(package_table->locked_lookup_only(pkg_list->at(x)) != NULL,
"Unable to create a " JAVA_BASE_NAME " package entry");
// Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of

View File

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,11 +37,30 @@
#include "runtime/handles.inline.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/ostream.hpp"
#include "utilities/quickSort.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
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
@ -169,28 +188,26 @@ void PackageEntry::delete_qualified_exports() {
_qualified_exports = NULL;
}
PackageEntryTable::PackageEntryTable(int table_size)
: Hashtable<Symbol*, mtModule>(table_size, sizeof(PackageEntry))
{
}
PackageEntryTable::PackageEntryTable() { }
PackageEntryTable::~PackageEntryTable() {
// Walk through all buckets and all entries in each bucket,
// freeing each entry.
for (int i = 0; i < table_size(); ++i) {
for (PackageEntry* p = bucket(i); p != NULL;) {
PackageEntry* to_remove = p;
// read next before freeing.
p = p->next();
// Clean out the C heap allocated qualified exports list first before freeing the entry
to_remove->delete_qualified_exports();
to_remove->name()->decrement_refcount();
BasicHashtable<mtModule>::free_entry(to_remove);
class PackageEntryTableDeleter : public StackObj {
public:
bool do_entry(const Symbol*& name, PackageEntry*& 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 package %s", str);
log_debug(module)("PackageEntry: deleting package: %s", str);
}
delete entry;
return true;
}
}
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
@ -225,21 +242,19 @@ PackageEntry* PackageEntry::get_archived_entry(PackageEntry* orig_entry) {
}
void PackageEntry::iterate_symbols(MetaspaceClosure* closure) {
closure->push(literal_addr()); // name
closure->push(&_name);
}
void PackageEntry::init_as_archived_entry() {
Array<ModuleEntry*>* archived_qualified_exports = ModuleEntry::write_growable_array(_qualified_exports);
set_next(NULL);
set_literal(ArchiveBuilder::get_relocated_symbol(literal()));
set_hash(0x0); // re-init at runtime
_name = ArchiveBuilder::get_relocated_symbol(_name);
_module = ModuleEntry::get_archived_entry(_module);
_qualified_exports = (GrowableArray<ModuleEntry*>*)archived_qualified_exports;
_defined_by_cds_in_class_path = 0;
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*)&_qualified_exports);
}
@ -255,38 +270,38 @@ static int compare_package_by_name(PackageEntry* a, PackageEntry* b) {
}
void PackageEntryTable::iterate_symbols(MetaspaceClosure* closure) {
for (int i = 0; i < table_size(); ++i) {
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
auto syms = [&] (const Symbol*& key, PackageEntry*& p) {
p->iterate_symbols(closure);
}
}
};
_table.iterate_all(syms);
}
Array<PackageEntry*>* PackageEntryTable::allocate_archived_entries() {
// First count the packages in named modules
int n, i;
for (n = 0, i = 0; i < table_size(); ++i) {
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
if (p->module()->name() != NULL) {
n++;
}
int n = 0;
auto count = [&] (const Symbol*& key, PackageEntry*& p) {
if (p->module()->is_named()) {
n++;
}
}
};
_table.iterate_all(count);
Array<PackageEntry*>* archived_packages = ArchiveBuilder::new_rw_array<PackageEntry*>(n);
for (n = 0, i = 0; i < table_size(); ++i) {
for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) {
if (p->module()->name() != NULL) {
// We don't archive unnamed modules, or packages in unnamed modules. They will be
// created on-demand at runtime as classes in such packages are loaded.
archived_packages->at_put(n++, p);
}
// reset n
n = 0;
auto grab = [&] (const Symbol*& key, PackageEntry*& p) {
if (p->module()->is_named()) {
// We don't archive unnamed modules, or packages in unnamed modules. They will be
// 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) {
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());
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++) {
PackageEntry* archived_entry = archived_packages->at(i);
archived_entry->load_from_archive();
unsigned int hash = compute_hash(archived_entry->name());
archived_entry->set_hash(hash);
add_entry(hash_to_index(hash), archived_entry);
_table.put(archived_entry->name(), archived_entry);
}
}
#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
// was taken by caller.
void PackageEntryTable::locked_create_entry(Symbol* name, ModuleEntry* module) {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
assert(locked_lookup_only(name) == NULL, "Package entry already exists");
PackageEntry* entry = new_entry(compute_hash(name), name, module);
add_entry(index_for(name), entry);
PackageEntry* entry = new PackageEntry(name, module);
bool created = _table.put(name, entry);
assert(created, "must be");
}
// Create package entry in loader's package entry table if it does not already
// 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");
// Check if package entry already exists. If not, create it.
if (locked_lookup_only(name) == NULL) {
locked_create_entry(name, module);
bool created;
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);
PackageEntry* p = locked_lookup_only(name);
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;
}
return locked_create_entry_if_absent(name, module);
}
PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
@ -373,33 +366,26 @@ PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
PackageEntry* PackageEntryTable::locked_lookup_only(Symbol* name) {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
int index = index_for(name);
for (PackageEntry* p = bucket(index); p != NULL; p = p->next()) {
if (p->name()->fast_compare(name) == 0) {
return p;
}
}
return NULL;
PackageEntry** entry = _table.get(name);
return entry == nullptr ? nullptr : *entry;
}
// Called when a define module for java.base is being processed.
// Verify the packages loaded thus far are in java.base's package list.
void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
assert_lock_strong(Module_lock);
for (int i = 0; i < table_size(); i++) {
for (PackageEntry* entry = bucket(i);
entry != NULL;
entry = entry->next()) {
ModuleEntry* m = entry->module();
Symbol* module_name = (m == NULL ? NULL : m->name());
if (module_name != NULL &&
(module_name->fast_compare(vmSymbols::java_base()) == 0) &&
!pkg_list->contains(entry->name())) {
ResourceMark rm;
vm_exit_during_initialization("A non-" JAVA_BASE_NAME " package was loaded prior to module system initialization", entry->name()->as_C_string());
}
auto verifier = [&] (const Symbol*& name, PackageEntry*& entry) {
ModuleEntry* m = entry->module();
Symbol* module_name = (m == NULL ? NULL : m->name());
if (module_name != NULL &&
(module_name->fast_compare(vmSymbols::java_base()) == 0) &&
!pkg_list->contains(entry->name())) {
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
@ -424,31 +410,48 @@ bool PackageEntry::exported_pending_delete() const {
// Remove dead entries from all packages' exported list
void PackageEntryTable::purge_all_package_exports() {
assert_locked_or_safepoint(Module_lock);
for (int i = 0; i < table_size(); i++) {
for (PackageEntry* entry = bucket(i);
entry != NULL;
entry = entry->next()) {
if (entry->exported_pending_delete()) {
// exported list is pending deletion due to a transition
// from qualified to unqualified
entry->delete_qualified_exports();
} else if (entry->is_qual_exported()) {
entry->purge_qualified_exports();
}
auto purge = [&] (const Symbol*& name, PackageEntry*& entry) {
if (entry->exported_pending_delete()) {
// exported list is pending deletion due to a transition
// from qualified to unqualified
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) {
auto printer = [&] (const Symbol*& name, PackageEntry*& entry) {
entry->print(st);
};
st->print_cr("Package Entry Table (table_size=%d, entries=%d)",
table_size(), number_of_entries());
for (int i = 0; i < table_size(); i++) {
for (PackageEntry* probe = bucket(i);
probe != NULL;
probe = probe->next()) {
probe->print(st);
}
}
_table.table_size(), _table.number_of_entries());
_table.iterate_all(printer);
}
// 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) {
ResourceMark rm;
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(),
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
_classpath_index, _export_flags == PKG_EXP_UNQUALIFIED,
_export_flags == PKG_EXP_ALLUNNAMED, p2i(next()));
}
void PackageEntryTable::verify() {
verify_table<PackageEntry>("Package Entry Table");
}
void PackageEntry::verify() {
guarantee(name() != NULL, "A package entry must have a corresponding symbol name.");
_export_flags == PKG_EXP_ALLUNNAMED);
}

View File

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,7 +29,7 @@
#include "oops/symbol.hpp"
#include "runtime/atomic.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_JFR
@ -38,6 +38,7 @@
template <class T> class Array;
class MetaspaceClosure;
class ModuleEntry;
// A PackageEntry basically represents a Java package. It contains:
// - Symbol* containing the package's name.
@ -97,8 +98,9 @@ class MetaspaceClosure;
#define PKG_EXP_ALLUNNAMED 0x0002
#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:
Symbol* _name;
ModuleEntry* _module;
// Indicates if package is exported unqualifiedly or to all unnamed. Access to
// 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.
volatile int _defined_by_cds_in_class_path;
public:
void init() {
_module = NULL;
_export_flags = 0;
_classpath_index = -1;
_must_walk_exports = false;
_qualified_exports = NULL;
_defined_by_cds_in_class_path = 0;
}
PackageEntry(Symbol* name, ModuleEntry* module);
~PackageEntry();
// package name
Symbol* name() const { return literal(); }
Symbol* name() const { return _name; }
// the module containing the package definition
ModuleEntry* module() const { return _module; }
@ -199,14 +195,6 @@ public:
void add_qexport(ModuleEntry* m);
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
void package_exports_do(ModuleClosure* f);
@ -217,7 +205,6 @@ public:
void delete_qualified_exports();
void print(outputStream* st = tty);
void verify();
#if INCLUDE_CDS_JAVA_HEAP
void iterate_symbols(MetaspaceClosure* closure);
@ -248,47 +235,24 @@ public:
// 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.
// The PackageEntryTable's lookup is lock free.
//
class PackageEntryTable : public Hashtable<Symbol*, mtModule> {
friend class VMStructs;
class PackageEntryTable : public CHeapObj<mtModule> {
ResourceHashtable<const Symbol*, PackageEntry*, 109, ResourceObj::C_HEAP, mtModule,
Symbol::compute_hash> _table;
public:
enum Constants {
_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
// lock was taken by caller.
void locked_create_entry(Symbol* name, ModuleEntry* module);
// Create package entry in loader's package entry table if it does not
// 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.
// 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.
// This will acquire the Module lock.
@ -303,8 +267,11 @@ public:
// purge dead weak references out of exported list
void purge_all_package_exports();
GrowableArray<PackageEntry*>* get_system_packages();
void packages_do(void f(PackageEntry*));
void print(outputStream* st = tty);
void verify();
#if INCLUDE_CDS_JAVA_HEAP
void iterate_symbols(MetaspaceClosure* closure);

View File

@ -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
// is defined by ModuleEntryTable::verify_javabase_packages check.
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 {
assert(loader_data->unnamed_module() != NULL, "unnamed module is NULL");
_package_entry = loader_data->packages()->lookup(pkg_name,
loader_data->unnamed_module());
_package_entry = loader_data->packages()->create_entry_if_absent(pkg_name, loader_data->unnamed_module());
}
// A package should have been successfully created

View File

@ -283,6 +283,5 @@ template class BasicHashtable<mtServiceability>;
template class BasicHashtable<mtLogging>;
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<PlaceholderEntry>(char const*);