8242452: During module definition, move conversion of packages from native to VM

8242290: Pointless verification in get_package_entry_by_name

Reviewed-by: lfoltan, iklam, hseigel
This commit is contained in:
Claes Redestad 2020-04-18 19:45:45 +02:00
parent 4d487927ad
commit d185fe9953
11 changed files with 202 additions and 309 deletions

View file

@ -40,49 +40,44 @@
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/reflection.hpp"
#include "utilities/stringUtils.hpp"
#include "utilities/utf8.hpp"
static bool verify_module_name(const char *module_name) {
if (module_name == NULL) return false;
int len = (int)strlen(module_name);
static bool verify_module_name(const char *module_name, int len) {
assert(module_name != NULL, "invariant");
return (len > 0 && len <= Symbol::max_length());
}
bool Modules::verify_package_name(const char* package_name) {
if (package_name == NULL) return false;
int len = (int)strlen(package_name);
static bool verify_package_name(const char* package_name, int len) {
assert(package_name != NULL, "Package name derived from non-null jstring can't be NULL");
return (len > 0 && len <= Symbol::max_length() &&
UTF8::is_legal_utf8((const unsigned char *)package_name, len, false) &&
ClassFileParser::verify_unqualified_name(package_name, len,
ClassFileParser::LegalClass));
}
static char* get_module_name(oop module, TRAPS) {
static char* get_module_name(oop module, int& len, TRAPS) {
oop name_oop = java_lang_Module::name(module);
if (name_oop == NULL) {
THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "Null module name");
}
char* module_name = java_lang_String::as_utf8_string(name_oop);
if (!verify_module_name(module_name)) {
char* module_name = java_lang_String::as_utf8_string(name_oop, len);
if (!verify_module_name(module_name, len)) {
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid module name: %s",
module_name != NULL ? module_name : "NULL"));
err_msg("Invalid module name: %s", module_name));
}
return module_name;
}
static const char* get_module_version(jstring version) {
if (version == NULL) {
static Symbol* as_symbol(jstring str_object) {
if (str_object == NULL) {
return NULL;
}
return java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(version));
int len;
char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(str_object), len);
return SymbolTable::new_symbol(str, len);
}
ModuleEntryTable* Modules::get_module_entry_table(Handle h_loader) {
@ -100,7 +95,7 @@ static PackageEntryTable* get_package_entry_table(Handle h_loader) {
}
static ModuleEntry* get_module_entry(jobject module, TRAPS) {
oop m = JNIHandles::resolve(module);
oop m = JNIHandles::resolve_non_null(module);
if (!java_lang_Module::is_instance(m)) {
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
"module is not an instance of type java.lang.Module");
@ -109,10 +104,10 @@ static ModuleEntry* get_module_entry(jobject module, TRAPS) {
}
static PackageEntry* get_locked_package_entry(ModuleEntry* module_entry, const char* package_name, TRAPS) {
static PackageEntry* get_locked_package_entry(ModuleEntry* module_entry, const char* package_name, int len, TRAPS) {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
assert(package_name != NULL, "Precondition");
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name);
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, len);
PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
assert(package_entry_table != NULL, "Unexpected null package entry table");
PackageEntry* package_entry = package_entry_table->locked_lookup_only(pkg_symbol);
@ -124,13 +119,10 @@ static PackageEntry* get_package_entry_by_name(Symbol* package,
Handle h_loader,
TRAPS) {
if (package != NULL) {
ResourceMark rm(THREAD);
if (Modules::verify_package_name(package->as_C_string())) {
PackageEntryTable* const package_entry_table =
get_package_entry_table(h_loader);
assert(package_entry_table != NULL, "Unexpected null package entry table");
return package_entry_table->lookup_only(package);
}
PackageEntryTable* const package_entry_table =
get_package_entry_table(h_loader);
assert(package_entry_table != NULL, "Unexpected null package entry table");
return package_entry_table->lookup_only(package);
}
return NULL;
}
@ -140,43 +132,50 @@ bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
return res != NULL;
}
static void define_javabase_module(jobject module, jstring version,
jstring location, const char* const* packages,
jsize num_packages, TRAPS) {
ResourceMark rm(THREAD);
// Converts the String oop to an internal package
// Will use the provided buffer if it's sufficiently large, otherwise allocates
// a resource array
// The length of the resulting string will be assigned to utf8_len
static const char* as_internal_package(oop package_string, char* buf, int buflen, int& utf8_len) {
char* package_name = java_lang_String::as_utf8_string_full(package_string, buf, buflen, utf8_len);
Handle module_handle(THREAD, JNIHandles::resolve(module));
// Obtain java.base's module version
const char* module_version = get_module_version(version);
TempNewSymbol version_symbol;
if (module_version != NULL) {
version_symbol = SymbolTable::new_symbol(module_version);
} else {
version_symbol = NULL;
}
// Obtain java.base's location
const char* module_location = NULL;
TempNewSymbol location_symbol = NULL;
if (location != NULL) {
module_location =
java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
if (module_location != NULL) {
location_symbol = SymbolTable::new_symbol(module_location);
// Turn all '/'s into '.'s
for (int index = 0; index < utf8_len; index++) {
if (package_name[index] == JVM_SIGNATURE_DOT) {
package_name[index] = JVM_SIGNATURE_SLASH;
}
}
return package_name;
}
static void define_javabase_module(Handle module_handle, jstring version, jstring location,
objArrayHandle pkgs, int num_packages, TRAPS) {
ResourceMark rm(THREAD);
// Obtain java.base's module version
TempNewSymbol version_symbol = as_symbol(version);
// Obtain java.base's location
TempNewSymbol location_symbol = as_symbol(location);
// Check that the packages are syntactically ok.
char buf[128];
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
const char *package_name = packages[x];
if (!Modules::verify_package_name(package_name)) {
oop pkg_str = pkgs->obj_at(x);
if (pkg_str == NULL || pkg_str->klass() != SystemDictionary::String_klass()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Bad package name"));
}
int package_len;
const char* package_name = as_internal_package(pkg_str, buf, sizeof(buf), package_len);
if (!verify_package_name(package_name, package_len)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: " JAVA_BASE_NAME, package_name));
}
Symbol* pkg_symbol = SymbolTable::new_symbol(package_name);
Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, package_len);
pkg_list->append(pkg_symbol);
}
@ -237,11 +236,11 @@ static void define_javabase_module(jobject module, jstring version,
ModuleEntryTable::patch_javabase_entries(module_handle);
log_info(module, load)(JAVA_BASE_NAME " location: %s",
module_location != NULL ? module_location : "NULL");
location_symbol != NULL ? location_symbol->as_C_string() : "NULL");
log_debug(module)("define_javabase_module(): Definition of module: "
JAVA_BASE_NAME ", version: %s, location: %s, package #: %d",
module_version != NULL ? module_version : "NULL",
module_location != NULL ? module_location : "NULL",
version_symbol != NULL ? version_symbol->as_C_string() : "NULL",
location_symbol != NULL ? location_symbol->as_C_string() : "NULL",
pkg_list->length());
// packages defined to java.base
@ -268,45 +267,37 @@ void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRA
}
void Modules::define_module(jobject module, jboolean is_open, jstring version,
jstring location, const char* const* packages,
jsize num_packages, TRAPS) {
jstring location, jobjectArray packages, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
}
if (num_packages < 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"num_packages must be >= 0");
}
if (packages == NULL && num_packages > 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"num_packages should be zero if packages is null");
}
Handle module_handle(THREAD, JNIHandles::resolve(module));
Handle module_handle(THREAD, JNIHandles::resolve_non_null(module));
if (!java_lang_Module::is_instance(module_handle())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module is not an instance of type java.lang.Module");
}
char* module_name = get_module_name(module_handle(), CHECK);
int module_name_len;
char* module_name = get_module_name(module_handle(), module_name_len, CHECK);
if (module_name == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Module name cannot be null");
}
// Resolve packages
objArrayHandle packages_h(THREAD, objArrayOop(JNIHandles::resolve(packages)));
int num_packages = (packages_h.is_null() ? 0 : packages_h->length());
// Special handling of java.base definition
if (strcmp(module_name, JAVA_BASE_NAME) == 0) {
assert(is_open == JNI_FALSE, "java.base module cannot be open");
define_javabase_module(module, version, location, packages, num_packages, CHECK);
define_javabase_module(module_handle, version, location, packages_h, num_packages, CHECK);
return;
}
const char* module_version = get_module_version(version);
oop loader = java_lang_Module::loader(module_handle());
// Make sure loader is not the jdk.internal.reflect.DelegatingClassLoader.
if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
@ -319,20 +310,31 @@ void Modules::define_module(jobject module, jboolean is_open, jstring version,
ClassLoaderData* loader_data = SystemDictionary::register_loader(h_loader);
assert(loader_data != NULL, "class loader data shouldn't be null");
// Only modules defined to either the boot or platform class loader, can define a "java/" package.
bool java_pkg_disallowed = !h_loader.is_null() &&
!SystemDictionary::is_platform_class_loader(h_loader());
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
char buf[128];
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
const char* package_name = packages[x];
if (!verify_package_name(package_name)) {
oop pkg_str = packages_h->obj_at(x);
if (pkg_str == NULL || pkg_str->klass() != SystemDictionary::String_klass()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Bad package name"));
}
int package_len;
const char* package_name = as_internal_package(pkg_str, buf, sizeof(buf), package_len);
if (!verify_package_name(package_name, package_len)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: %s",
package_name, module_name));
}
// Only modules defined to either the boot or platform class loader, can define a "java/" package.
if (!h_loader.is_null() &&
!SystemDictionary::is_platform_class_loader(h_loader()) &&
if (java_pkg_disallowed &&
(strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0 &&
(package_name[JAVAPKG_LEN] == JVM_SIGNATURE_SLASH || package_name[JAVAPKG_LEN] == '\0'))) {
const char* class_loader_name = loader_data->loader_name_and_id();
@ -348,7 +350,7 @@ void Modules::define_module(jobject module, jboolean is_open, jstring version,
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
Symbol* pkg_symbol = SymbolTable::new_symbol(package_name);
Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, package_len);
pkg_list->append(pkg_symbol);
}
@ -356,28 +358,15 @@ void Modules::define_module(jobject module, jboolean is_open, jstring version,
assert(module_table != NULL, "module entry table shouldn't be null");
// Create symbol* entry for module name.
TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name);
TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, module_name_len);
bool dupl_modules = false;
// Create symbol* entry for module version.
TempNewSymbol version_symbol;
if (module_version != NULL) {
version_symbol = SymbolTable::new_symbol(module_version);
} else {
version_symbol = NULL;
}
// Create symbol for module version.
TempNewSymbol version_symbol = as_symbol(version);
// Create symbol* entry for module location.
const char* module_location = NULL;
TempNewSymbol location_symbol = NULL;
if (location != NULL) {
module_location =
java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
if (module_location != NULL) {
location_symbol = SymbolTable::new_symbol(module_location);
}
}
TempNewSymbol location_symbol = as_symbol(location);
PackageEntryTable* package_table = NULL;
PackageEntry* existing_pkg = NULL;
@ -439,13 +428,13 @@ void Modules::define_module(jobject module, jboolean is_open, jstring version,
}
log_info(module, load)("%s location: %s", module_name,
module_location != NULL ? module_location : "NULL");
location_symbol != NULL ? location_symbol->as_C_string() : "NULL");
LogTarget(Debug, module) lt;
if (lt.is_enabled()) {
LogStream ls(lt);
ls.print("define_module(): creation of module: %s, version: %s, location: %s, ",
module_name, module_version != NULL ? module_version : "NULL",
module_location != NULL ? module_location : "NULL");
module_name, version_symbol != NULL ? version_symbol->as_C_string() : "NULL",
location_symbol != NULL ? location_symbol->as_C_string() : "NULL");
loader_data->print_value_on(&ls);
ls.print_cr(", package #: %d", pkg_list->length());
for (int y = 0; y < pkg_list->length(); y++) {
@ -486,7 +475,6 @@ void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader must be the boot class loader");
}
Handle h_loader(THREAD, loader);
log_debug(module)("set_bootloader_unnamed_module(): recording unnamed module for boot loader");
@ -499,7 +487,8 @@ void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
java_lang_Module::set_module_entry(module_handle(), unnamed_module);
}
void Modules::add_module_exports(jobject from_module, const char* package_name, jobject to_module, TRAPS) {
void Modules::add_module_exports(jobject from_module, jstring package_name, jobject to_module, TRAPS) {
if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
@ -529,9 +518,14 @@ void Modules::add_module_exports(jobject from_module, const char* package_name,
}
PackageEntry* package_entry = NULL;
char buf[128];
int package_len;
ResourceMark rm(THREAD);
const char* pkg = as_internal_package(JNIHandles::resolve_non_null(package_name), buf, sizeof(buf), package_len);
{
MutexLocker ml(THREAD, Module_lock);
package_entry = get_locked_package_entry(from_module_entry, package_name, CHECK);
package_entry = get_locked_package_entry(from_module_entry, pkg, package_len, CHECK);
// Do nothing if modules are the same
// If the package is not found we'll throw an exception later
if (from_module_entry != to_module_entry &&
@ -542,15 +536,13 @@ void Modules::add_module_exports(jobject from_module, const char* package_name,
// Handle errors and logging outside locked section
if (package_entry == NULL) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in from_module %s",
package_name != NULL ? package_name : "",
pkg != NULL ? pkg : "",
from_module_entry->name()->as_C_string()));
}
if (log_is_enabled(Debug, module)) {
ResourceMark rm(THREAD);
log_debug(module)("add_module_exports(): package %s in module %s is exported to module %s",
package_entry->name()->as_C_string(),
from_module_entry->name()->as_C_string(),
@ -561,7 +553,7 @@ void Modules::add_module_exports(jobject from_module, const char* package_name,
}
void Modules::add_module_exports_qualified(jobject from_module, const char* package,
void Modules::add_module_exports_qualified(jobject from_module, jstring package,
jobject to_module, TRAPS) {
if (to_module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
@ -675,7 +667,7 @@ jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRA
}
// Export package in module to all unnamed modules.
void Modules::add_module_exports_to_all_unnamed(jobject module, const char* package_name, TRAPS) {
void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package_name, TRAPS) {
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
@ -694,10 +686,14 @@ void Modules::add_module_exports_to_all_unnamed(jobject module, const char* pack
if (!module_entry->is_named() || module_entry->is_open())
return;
ResourceMark rm(THREAD);
char buf[128];
int pkg_len;
const char* pkg = as_internal_package(JNIHandles::resolve_non_null(package_name), buf, sizeof(buf), pkg_len);
PackageEntry* package_entry = NULL;
{
MutexLocker m1(THREAD, Module_lock);
package_entry = get_locked_package_entry(module_entry, package_name, CHECK);
package_entry = get_locked_package_entry(module_entry, pkg, pkg_len, CHECK);
// Mark package as exported to all unnamed modules.
if (package_entry != NULL) {
@ -707,15 +703,13 @@ void Modules::add_module_exports_to_all_unnamed(jobject module, const char* pack
// Handle errors and logging outside locked section
if (package_entry == NULL) {
ResourceMark rm(THREAD);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in module %s",
package_name != NULL ? package_name : "",
pkg != NULL ? pkg : "",
module_entry->name()->as_C_string()));
}
if (log_is_enabled(Debug, module)) {
ResourceMark rm(THREAD);
log_debug(module)("add_module_exports_to_all_unnamed(): package %s in module"
" %s is exported to all unnamed modules",
package_entry->name()->as_C_string(),