Skip to content
Permalink
Browse files

8241371: Refactor and consolidate package_from_name

Reviewed-by: iklam, lfoltan
  • Loading branch information
cl4es committed Mar 23, 2020
1 parent 7dc952e commit 23d6a788b4685db1672b72430431beb7425c3803
@@ -5877,16 +5877,16 @@ void ClassFileParser::prepend_host_package_name(const InstanceKlass* unsafe_anon
ResourceMark rm(THREAD);
assert(strrchr(_class_name->as_C_string(), JVM_SIGNATURE_SLASH) == NULL,
"Unsafe anonymous class should not be in a package");
const char* host_pkg_name =
ClassLoader::package_from_name(unsafe_anonymous_host->name()->as_C_string(), NULL);
TempNewSymbol host_pkg_name =
ClassLoader::package_from_class_name(unsafe_anonymous_host->name());

if (host_pkg_name != NULL) {
int host_pkg_len = (int)strlen(host_pkg_name);
int host_pkg_len = host_pkg_name->utf8_length();
int class_name_len = _class_name->utf8_length();
int symbol_len = host_pkg_len + 1 + class_name_len;
char* new_anon_name = NEW_RESOURCE_ARRAY(char, symbol_len + 1);
int n = os::snprintf(new_anon_name, symbol_len + 1, "%s/%.*s",
host_pkg_name, class_name_len, _class_name->base());
int n = os::snprintf(new_anon_name, symbol_len + 1, "%.*s/%.*s",
host_pkg_len, host_pkg_name->base(), class_name_len, _class_name->base());
assert(n == symbol_len, "Unexpected number of characters in string");

// Decrement old _class_name to avoid leaking.
@@ -72,6 +72,7 @@
#include "utilities/events.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/macros.hpp"
#include "utilities/utf8.hpp"

// Entry point in java.dll for path canonicalization

@@ -177,75 +178,58 @@ bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
}

// Used to obtain the package name from a fully qualified class name.
// It is the responsibility of the caller to establish a ResourceMark.
const char* ClassLoader::package_from_name(const char* const class_name, bool* bad_class_name) {
if (class_name == NULL) {
Symbol* ClassLoader::package_from_class_name(const Symbol* name, bool* bad_class_name) {
if (name == NULL) {
if (bad_class_name != NULL) {
*bad_class_name = true;
}
return NULL;
}

if (bad_class_name != NULL) {
*bad_class_name = false;
}

const char* const last_slash = strrchr(class_name, JVM_SIGNATURE_SLASH);
if (last_slash == NULL) {
// No package name
int utf_len = name->utf8_length();
const jbyte* base = (const jbyte*)name->base();
const jbyte* start = base;
const jbyte* end = UTF8::strrchr(start, utf_len, JVM_SIGNATURE_SLASH);
if (end == NULL) {
return NULL;
}

char* class_name_ptr = (char*) class_name;
// Skip over '['s
if (*class_name_ptr == JVM_SIGNATURE_ARRAY) {
if (*start == JVM_SIGNATURE_ARRAY) {
do {
class_name_ptr++;
} while (*class_name_ptr == JVM_SIGNATURE_ARRAY);
start++;
} while (start < end && *start == JVM_SIGNATURE_ARRAY);

// Fully qualified class names should not contain a 'L'.
// Set bad_class_name to true to indicate that the package name
// could not be obtained due to an error condition.
// In this situation, is_same_class_package returns false.
if (*class_name_ptr == JVM_SIGNATURE_CLASS) {
if (*start == JVM_SIGNATURE_CLASS) {
if (bad_class_name != NULL) {
*bad_class_name = true;
}
return NULL;
}
}

int length = last_slash - class_name_ptr;

// A class name could have just the slash character in the name.
if (length <= 0) {
// A class name could have just the slash character in the name,
// in which case start > end
if (start >= end) {
// No package name
if (bad_class_name != NULL) {
*bad_class_name = true;
}
return NULL;
}

// drop name after last slash (including slash)
// Ex., "java/lang/String.class" => "java/lang"
char* pkg_name = NEW_RESOURCE_ARRAY(char, length + 1);
strncpy(pkg_name, class_name_ptr, length);
*(pkg_name+length) = '\0';

return (const char *)pkg_name;
return SymbolTable::new_symbol(name, start - base, end - base);
}

// Given a fully qualified class name, find its defining package in the class loader's
// package entry table.
PackageEntry* ClassLoader::get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
ResourceMark rm(THREAD);
const char *pkg_name = ClassLoader::package_from_name(class_name);
PackageEntry* ClassLoader::get_package_entry(Symbol* pkg_name, ClassLoaderData* loader_data, TRAPS) {
if (pkg_name == NULL) {
return NULL;
}
PackageEntryTable* pkgEntryTable = loader_data->packages();
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(pkg_name);
return pkgEntryTable->lookup_only(pkg_symbol);
return pkgEntryTable->lookup_only(pkg_name);
}

const char* ClassPathEntry::copy_path(const char* path) {
@@ -407,14 +391,14 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(const char* name, C
JImageLocationRef location = (*JImageFindResource)(_jimage, "", get_jimage_version_string(), name, &size);

if (location == 0) {
ResourceMark rm;
const char* pkg_name = ClassLoader::package_from_name(name);
TempNewSymbol class_name = SymbolTable::new_symbol(name);
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);

if (pkg_name != NULL) {
if (!Universe::is_module_initialized()) {
location = (*JImageFindResource)(_jimage, JAVA_BASE_NAME, get_jimage_version_string(), name, &size);
} else {
PackageEntry* package_entry = ClassLoader::get_package_entry(name, loader_data, CHECK_NULL);
PackageEntry* package_entry = ClassLoader::get_package_entry(pkg_name, loader_data, CHECK_NULL);
if (package_entry != NULL) {
ResourceMark rm;
// Get the module name
@@ -1029,25 +1013,22 @@ int ClassLoader::crc32(int crc, const char* buf, int len) {
return (*Crc32)(crc, (const jbyte*)buf, len);
}

// Function add_package extracts the package from the fully qualified class name
// and checks if the package is in the boot loader's package entry table. If so,
// then it sets the classpath_index in the package entry record.
// Function add_package checks if the package of the InstanceKlass is in the
// boot loader's package entry table. If so, then it sets the classpath_index
// in the package entry record.
//
// The classpath_index field is used to find the entry on the boot loader class
// path for packages with classes loaded by the boot loader from -Xbootclasspath/a
// in an unnamed module. It is also used to indicate (for all packages whose
// classes are loaded by the boot loader) that at least one of the package's
// classes has been loaded.
bool ClassLoader::add_package(const char *fullq_class_name, s2 classpath_index, TRAPS) {
assert(fullq_class_name != NULL, "just checking");
bool ClassLoader::add_package(const InstanceKlass* ik, s2 classpath_index, TRAPS) {
assert(ik != NULL, "just checking");

// Get package name from fully qualified class name.
ResourceMark rm(THREAD);
const char *cp = package_from_name(fullq_class_name);
if (cp != NULL) {
PackageEntry* ik_pkg = ik->package();
if (ik_pkg != NULL) {
PackageEntryTable* pkg_entry_tbl = ClassLoaderData::the_null_class_loader_data()->packages();
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(cp);
PackageEntry* pkg_entry = pkg_entry_tbl->lookup_only(pkg_symbol);
PackageEntry* pkg_entry = pkg_entry_tbl->lookup_only(ik_pkg->name());
if (pkg_entry != NULL) {
assert(classpath_index != -1, "Unexpected classpath_index");
pkg_entry->set_classpath_index(classpath_index);
@@ -1166,7 +1147,9 @@ ClassFileStream* ClassLoader::search_module_entries(const GrowableArray<ModuleCl
ClassFileStream* stream = NULL;

// Find the class' defining module in the boot loader's module entry table
PackageEntry* pkg_entry = get_package_entry(class_name, ClassLoaderData::the_null_class_loader_data(), CHECK_NULL);
TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
TempNewSymbol pkg_name = package_from_class_name(class_name_symbol);
PackageEntry* pkg_entry = get_package_entry(pkg_name, ClassLoaderData::the_null_class_loader_data(), CHECK_NULL);
ModuleEntry* mod_entry = (pkg_entry != NULL) ? pkg_entry->module() : NULL;

// If the module system has not defined java.base yet, then
@@ -1317,7 +1300,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
return NULL;
}

if (!add_package(file_name, classpath_index, THREAD)) {
if (!add_package(result, classpath_index, THREAD)) {
return NULL;
}

@@ -260,21 +260,21 @@ class ClassLoader: AllStatic {
bool is_boot_append,
bool from_class_path_attr, TRAPS);

// If the package for the fully qualified class name is in the boot
// loader's package entry table then add_package() sets the classpath_index
// field so that get_system_package() will know to return a non-null value
// for the package's location. And, so that the package will be added to
// the list of packages returned by get_system_packages().
// If the package for InstanceKlass is in the boot loader's package entry
// table then add_package() sets the classpath_index field so that
// get_system_package() will know to return a non-null value for the
// package's location. And, so that the package will be added to the list of
// packages returned by get_system_packages().
// For packages whose classes are loaded from the boot loader class path, the
// classpath_index indicates which entry on the boot loader class path.
static bool add_package(const char *fullq_class_name, s2 classpath_index, TRAPS);
static bool add_package(const InstanceKlass* ik, s2 classpath_index, TRAPS);

// Canonicalizes path names, so strcmp will work properly. This is mainly
// to avoid confusing the zip library
static bool get_canonical_path(const char* orig, char* out, int len);
static const char* file_name_for_class_name(const char* class_name,
int class_name_len);
static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS);
static PackageEntry* get_package_entry(Symbol* pkg_name, ClassLoaderData* loader_data, TRAPS);

public:
static int crc32(int crc, const char* buf, int len);
@@ -440,10 +440,10 @@ class ClassLoader: AllStatic {

static bool string_ends_with(const char* str, const char* str_to_find);

// obtain package name from a fully qualified class name
// Extract package name from a fully qualified class name
// *bad_class_name is set to true if there's a problem with parsing class_name, to
// distinguish from a class_name with no package name, as both cases have a NULL return value
static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL);
static Symbol* package_from_class_name(const Symbol* class_name, bool* bad_class_name = NULL);

// Debugging
static void verify() PRODUCT_RETURN;
@@ -94,8 +94,7 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook(
}

if (class_loader.is_null()) {
ResourceMark rm;
ClassLoader::add_package(class_name->as_C_string(), path_index, THREAD);
ClassLoader::add_package(new_ik, path_index, THREAD);
}

return new_ik;
@@ -1197,25 +1197,23 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
return true;
}
// Get the pkg_entry from the classloader
TempNewSymbol pkg_name = NULL;
PackageEntry* pkg_entry = NULL;
ModuleEntry* mod_entry = NULL;
pkg_name = InstanceKlass::package_from_name(class_name, CHECK_false);
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
if (pkg_name != NULL) {
if (loader_data != NULL) {
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
}
if (pkg_entry != NULL) {
mod_entry = pkg_entry->module();
if (pkg_entry != NULL) {
mod_entry = pkg_entry->module();
// If the archived class is from a module that has been patched at runtime,
// the class cannot be loaded from the archive.
if (mod_entry != NULL && mod_entry->is_patched()) {
return false;
}
}
}
}

// If the archived class is from a module that has been patched at runtime,
// the class cannot be loaded from the archive.
if (mod_entry != NULL && mod_entry->is_patched()) {
return false;
}

if (class_loader.is_null()) {
assert(ent != NULL, "Shared class for NULL classloader must have valid SharedClassPathEntry");
// The NULL classloader can load archived class originated from the
@@ -1357,8 +1355,7 @@ void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData
// package was loaded.
if (loader_data->is_the_null_class_loader_data()) {
int path_index = ik->shared_classpath_index();
ResourceMark rm(THREAD);
ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
ClassLoader::add_package(ik, path_index, THREAD);
}

if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
@@ -1430,7 +1427,7 @@ InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle
ClassLoaderData *loader_data = class_loader_data(class_loader);

// Find the package in the boot loader's package entry table.
TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK_NULL);
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
if (pkg_name != NULL) {
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
}
@@ -443,9 +443,9 @@ Handle SystemDictionaryShared::get_shared_jar_url(int shared_path_index, TRAPS)
Handle SystemDictionaryShared::get_package_name(Symbol* class_name, TRAPS) {
ResourceMark rm(THREAD);
Handle pkgname_string;
char* pkgname = (char*) ClassLoader::package_from_name((const char*) class_name->as_C_string());
if (pkgname != NULL) { // Package prefix found
StringUtils::replace_no_expand(pkgname, "/", ".");
Symbol* pkg = ClassLoader::package_from_class_name(class_name);
if (pkg != NULL) { // Package prefix found
const char* pkgname = pkg->as_klass_external_name();
pkgname_string = java_lang_String::create_from_str(pkgname,
CHECK_(pkgname_string));
}
@@ -602,7 +602,7 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
ClassLoaderData *loader_data =
ClassLoaderData::class_loader_data(class_loader());
PackageEntryTable* pkgEntryTable = loader_data->packages();
TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK_(pd));
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
if (pkg_name != NULL) {
PackageEntry* pkg_entry = pkgEntryTable->lookup_only(pkg_name);
if (pkg_entry != NULL) {
@@ -2641,24 +2641,6 @@ const char* InstanceKlass::signature_name() const {
return dest;
}

// Used to obtain the package name from a fully qualified class name.
Symbol* InstanceKlass::package_from_name(const Symbol* name, TRAPS) {
if (name == NULL) {
return NULL;
} else {
if (name->utf8_length() <= 0) {
return NULL;
}
ResourceMark rm(THREAD);
const char* package_name = ClassLoader::package_from_name((const char*) name->as_C_string());
if (package_name == NULL) {
return NULL;
}
Symbol* pkg_name = SymbolTable::new_symbol(package_name);
return pkg_name;
}
}

ModuleEntry* InstanceKlass::module() const {
// For an unsafe anonymous class return the host class' module
if (is_unsafe_anonymous()) {
@@ -2680,7 +2662,7 @@ void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) {
// ensure java/ packages only loaded by boot or platform builtin loaders
check_prohibited_package(name(), loader_data, CHECK);

TempNewSymbol pkg_name = package_from_name(name(), CHECK);
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(name());

if (pkg_name != NULL && loader_data != NULL) {

@@ -2776,25 +2758,24 @@ bool InstanceKlass::is_same_class_package(oop other_class_loader,
ResourceMark rm;

bool bad_class_name = false;
const char* other_pkg =
ClassLoader::package_from_name((const char*) other_class_name->as_C_string(), &bad_class_name);
TempNewSymbol other_pkg = ClassLoader::package_from_class_name(other_class_name, &bad_class_name);
if (bad_class_name) {
return false;
}
// Check that package_from_name() returns NULL, not "", if there is no package.
assert(other_pkg == NULL || strlen(other_pkg) > 0, "package name is empty string");
// Check that package_from_class_name() returns NULL, not "", if there is no package.
assert(other_pkg == NULL || other_pkg->utf8_length() > 0, "package name is empty string");

const Symbol* const this_package_name =
this->package() != NULL ? this->package()->name() : NULL;

if (this_package_name == NULL || other_pkg == NULL) {
// One of the two doesn't have a package. Only return true if the other
// one also doesn't have a package.
return (const char*)this_package_name == other_pkg;
return this_package_name == other_pkg;
}

// Check if package is identical
return this_package_name->equals(other_pkg);
return this_package_name->fast_compare(other_pkg) == 0;
}
}

@@ -2828,7 +2809,7 @@ void InstanceKlass::check_prohibited_package(Symbol* class_name,
ResourceMark rm(THREAD);
char* name = class_name->as_C_string();
if (strncmp(name, JAVAPKG, JAVAPKG_LEN) == 0 && name[JAVAPKG_LEN] == '/') {
TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK);
TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
name = pkg_name->as_C_string();
const char* class_loader_name = loader_data->loader_name_and_id();

0 comments on commit 23d6a78

Please sign in to comment.