8169069: Module system implementation refresh (11/2016)

Co-authored-by: Lois Foltan <lois.foltan@oracle.com>
Co-authored-by: Harold Seigel <harold.seigel@oracle.com>
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com>
Co-authored-by: George Triantafillou <george.triantafillou@oracle.com>
Reviewed-by: lfoltan, acorn, ctornqvi, mchung
This commit is contained in:
Alan Bateman 2016-12-01 08:56:41 +00:00
parent 16734f37d5
commit 988690303a
110 changed files with 1885 additions and 773 deletions

View file

@ -34,6 +34,7 @@
#include "classfile/packageEntry.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
@ -44,6 +45,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/reflection.hpp"
#include "utilities/stringUtils.hpp"
#include "utilities/utf8.hpp"
static bool verify_module_name(char *module_name) {
@ -290,6 +292,14 @@ void Modules::define_module(jobject module, jstring version,
const char* module_version = get_module_version(version);
oop loader = java_lang_reflect_Module::loader(module_handle());
// Make sure loader is not the jdk.internal.reflect.DelegatingClassLoader.
if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader is an invalid delegating class loader");
}
Handle h_loader = Handle(THREAD, loader);
objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
objArrayHandle packages_h(THREAD, packages_oop);
int num_packages = (packages_h == NULL ? 0 : packages_h->length());
@ -310,6 +320,21 @@ void Modules::define_module(jobject module, jstring version,
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) &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(h_loader());
StringUtils::replace_no_expand(package_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
// append_if_missing() returns FALSE if entry already exists.
if (!pkg_list->append_if_missing(pkg_symbol)) {
@ -319,20 +344,6 @@ void Modules::define_module(jobject module, jstring version,
}
}
oop loader = java_lang_reflect_Module::loader(module_handle());
// Make sure loader is not the sun.reflect.DelegatingClassLoader.
if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader is an invalid delegating class loader");
}
Handle h_loader = Handle(THREAD, loader);
// Check that loader is a subclass of java.lang.ClassLoader.
if (loader != NULL && !java_lang_ClassLoader::is_subclass(h_loader->klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader is not a subclass of java.lang.ClassLoader");
}
ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
assert(module_table != NULL, "module entry table shouldn't be null");
@ -595,122 +606,6 @@ void Modules::add_reads_module(jobject from_module, jobject to_module, TRAPS) {
}
}
jboolean Modules::can_read_module(jobject asking_module, jobject target_module, TRAPS) {
if (asking_module == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"asking_module is null", JNI_FALSE);
}
ModuleEntry* asking_module_entry = get_module_entry(asking_module, CHECK_false);
if (asking_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"asking_module is invalid", JNI_FALSE);
}
// Calling can_read_all_unnamed() with NULL tests if a module is loose.
if (target_module == NULL) {
return asking_module_entry->can_read_all_unnamed();
}
ModuleEntry* target_module_entry = get_module_entry(target_module, CHECK_false);
if (target_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"target_module is invalid", JNI_FALSE);
}
ResourceMark rm(THREAD);
log_debug(modules)("can_read_module(): module %s trying to read module %s, allowed = %s",
asking_module_entry->is_named() ?
asking_module_entry->name()->as_C_string() : UNNAMED_MODULE,
target_module_entry->is_named() ?
target_module_entry->name()->as_C_string() : UNNAMED_MODULE,
BOOL_TO_STR(asking_module_entry == target_module_entry ||
(asking_module_entry->can_read_all_unnamed() &&
!target_module_entry->is_named()) ||
asking_module_entry->can_read(target_module_entry)));
// Return true if:
// 1. the modules are the same, or
// 2. the asking_module is unnamed (because unnamed modules read everybody), or
// 3. the asking_module is loose and the target module is unnamed, or
// 4. if can_read() returns true.
if (asking_module_entry == target_module_entry ||
(asking_module_entry->can_read_all_unnamed() && !target_module_entry->is_named())) {
return true;
}
return asking_module_entry->can_read(target_module_entry);
}
jboolean Modules::is_exported_to_module(jobject from_module, jstring package,
jobject to_module, TRAPS) {
if (package == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"package is null", JNI_FALSE);
}
if (from_module == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"from_module is null", JNI_FALSE);
}
ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK_false);
if (from_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"from_module is invalid", JNI_FALSE);
}
ModuleEntry* to_module_entry;
if (to_module == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"to_module is null", JNI_FALSE);
}
to_module_entry = get_module_entry(to_module, CHECK_false);
if (to_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"to_module is invalid", JNI_FALSE);
}
PackageEntry *package_entry = get_package_entry(from_module_entry, package,
CHECK_false);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package not found in from_module: %s",
from_module_entry->is_named() ?
from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
JNI_FALSE);
}
if (package_entry->module() != from_module_entry) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package: %s found in module %s, not in from_module: %s",
package_entry->name()->as_C_string(),
package_entry->module()->is_named() ?
package_entry->module()->name()->as_C_string() : UNNAMED_MODULE,
from_module_entry->is_named() ?
from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
JNI_FALSE);
}
log_debug(modules)("is_exported_to_module: package %s from module %s checking"
" if exported to module %s, exported? = %s",
package_entry->name()->as_C_string(),
from_module_entry->is_named() ?
from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
to_module_entry->is_named() ?
to_module_entry->name()->as_C_string() : UNNAMED_MODULE,
BOOL_TO_STR(!from_module_entry->is_named() ||
package_entry->is_unqual_exported() ||
from_module_entry == to_module_entry ||
package_entry->is_qexported_to(to_module_entry)));
// Return true if:
// 1. from_module is unnamed because unnamed modules export all their packages (by default), or
// 2. if the package is unqualifiedly exported, or
// 3. if the modules are the same, or
// 4. if the package is exported to to_module
return (!from_module_entry->is_named() ||
package_entry->is_unqual_exported() ||
from_module_entry == to_module_entry ||
package_entry->is_qexported_to(to_module_entry));
}
// This method is called by JFR and JNI.
jobject Modules::get_module(jclass clazz, TRAPS) {
assert(ModuleEntryTable::javabase_defined(), "Attempt to call get_module before java.base is defined");
@ -860,11 +755,27 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
err_msg("Invalid package name: %s", package_name));
}
ClassLoaderData *loader_data = module_entry->loader_data();
// Only modules defined to either the boot or platform class loader, can define a "java/" package.
if (!loader_data->is_the_null_class_loader_data() &&
!loader_data->is_platform_class_loader_data() &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(loader_data);
StringUtils::replace_no_expand(package_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
log_debug(modules)("add_module_package(): Adding package %s to module %s",
package_name, module_entry->name()->as_C_string());
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
PackageEntryTable* package_table = module_entry->loader_data()->packages();
PackageEntryTable* package_table = loader_data->packages();
assert(package_table != NULL, "Missing package_table");
bool pkg_exists = false;