8142968: Module System implementation

Initial integration of JEP 200, JEP 260, JEP 261, and JEP 282

Co-authored-by: Alex Buckley <alex.buckley@oracle.com>
Co-authored-by: Jonathan Gibbons <jonathan.gibbons@oracle.com>
Co-authored-by: Karen Kinnear <karen.kinnear@oracle.com>
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
Co-authored-by: Mark Reinhold <mark.reinhold@oracle.com>
Co-authored-by: Harold Seigel <harold.seigel@oracle.com>
Co-authored-by: Lois Foltan <lois.foltan@oracle.com>
Co-authored-by: Calvin Cheung <calvin.cheung@oracle.com>
Co-authored-by: Christian Tornqvist <christian.tornqvist@oracle.com>
Co-authored-by: Erik Joelsson <erik.joelsson@oracle.com>
Co-authored-by: George Triantafillou <george.triantafillou@oracle.com>
Co-authored-by: Igor Ignatyev <igor.ignatyev@oracle.com>
Co-authored-by: Ioi Lam <ioi.lam@oracle.com>
Co-authored-by: James Laskey <james.laskey@oracle.com>
Co-authored-by: Jean-Francois Denise <jean-francois.denise@oracle.com>
Co-authored-by: Jiangli Zhou <jiangli.zhou@oracle.com>
Co-authored-by: Markus Gronlund <markus.gronlund@oracle.com>
Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com>
Co-authored-by: Staffan Larsen <staffan.larsen@oracle.com>
Co-authored-by: Sundararajan Athijegannathan <sundararajan.athijegannathan@oracle.com>
Reviewed-by: acorn, ccheung, coleenp, ctornqvi, dholmes, dsimms, gtriantafill, iklam, jiangli, mgronlun, mseledtsov, cjplummer, sspitsyn, stefank, twisti, hseigel, lfoltan, alanb, mchung, dfazunen
This commit is contained in:
Alan Bateman 2016-03-17 19:04:01 +00:00
parent 007b0fa3db
commit f30fc1c88b
297 changed files with 15848 additions and 2302 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2016, 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
@ -1972,8 +1972,9 @@ static void restore_unshareable_in_class(Klass* k, TRAPS) {
}
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
instanceKlassHandle ik(THREAD, this);
ik->set_package(loader_data, CHECK);
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
Array<Method*>* methods = ik->methods();
int num_methods = methods->length();
@ -2178,26 +2179,135 @@ const char* InstanceKlass::signature_name() const {
return dest;
}
// different verisons of is_same_class_package
bool InstanceKlass::is_same_class_package(const Klass* class2) const {
const Klass* const class1 = (const Klass* const)this;
oop classloader1 = InstanceKlass::cast(class1)->class_loader();
const Symbol* const classname1 = class1->name();
const jbyte* InstanceKlass::package_from_name(const Symbol* name, int& length) {
ResourceMark rm;
length = 0;
if (name == NULL) {
return NULL;
} else {
const jbyte* base_name = name->base();
const jbyte* last_slash = UTF8::strrchr(base_name, name->utf8_length(), '/');
if (last_slash == NULL) {
// No package name
return NULL;
} else {
// Skip over '['s
if (*base_name == '[') {
do {
base_name++;
} while (*base_name == '[');
if (*base_name != 'L') {
// Fully qualified class names should not contain a 'L'.
// Set length to -1 to indicate that the package name
// could not be obtained due to an error condition.
// In this situtation, is_same_class_package returns false.
length = -1;
return NULL;
}
}
// Found the package name, look it up in the symbol table.
length = last_slash - base_name;
assert(length > 0, "Bad length for package name");
return base_name;
}
}
}
ModuleEntry* InstanceKlass::module() const {
if (!in_unnamed_package()) {
return _package_entry->module();
}
const Klass* host = host_klass();
if (host == NULL) {
return class_loader_data()->modules()->unnamed_module();
}
return host->class_loader_data()->modules()->unnamed_module();
}
void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) {
int length = 0;
const jbyte* base_name = package_from_name(name(), length);
if (base_name != NULL && loader_data != NULL) {
TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)base_name, length, CHECK);
// Find in class loader's package entry table.
_package_entry = loader_data->packages()->lookup_only(pkg_name);
// If the package name is not found in the loader's package
// entry table, it is an indication that the package has not
// been defined. Consider it defined within the unnamed module.
if (_package_entry == NULL) {
ResourceMark rm;
if (!ModuleEntryTable::javabase_defined()) {
// Before java.base is defined during bootstrapping, define all packages in
// the java.base module. If a non-java.base package is erroneously placed
// in the java.base module it will be caught later when java.base
// is defined by ModuleEntryTable::verify_javabase_packages check.
assert(ModuleEntryTable::javabase_module() != NULL, "java.base module is NULL");
_package_entry = loader_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_module());
} else {
assert(loader_data->modules()->unnamed_module() != NULL, "unnamed module is NULL");
_package_entry = loader_data->packages()->lookup(pkg_name,
loader_data->modules()->unnamed_module());
}
// A package should have been successfully created
assert(_package_entry != NULL, "Package entry for class %s not found, loader %s",
name()->as_C_string(), loader_data->loader_name());
}
if (log_is_enabled(Debug, modules)) {
ResourceMark rm;
ModuleEntry* m = _package_entry->module();
log_trace(modules)("Setting package: class: %s, package: %s, loader: %s, module: %s",
external_name(),
pkg_name->as_C_string(),
loader_data->loader_name(),
(m->is_named() ? m->name()->as_C_string() : UNNAMED_MODULE));
}
} else {
ResourceMark rm;
log_trace(modules)("Setting package: class: %s, package: unnamed, loader: %s, module: %s",
external_name(),
(loader_data != NULL) ? loader_data->loader_name() : "NULL",
UNNAMED_MODULE);
}
}
// different versions of is_same_class_package
bool InstanceKlass::is_same_class_package(const Klass* class2) const {
oop classloader1 = this->class_loader();
PackageEntry* classpkg1 = this->package();
if (class2->is_objArray_klass()) {
class2 = ObjArrayKlass::cast(class2)->bottom_klass();
}
oop classloader2;
PackageEntry* classpkg2;
if (class2->is_instance_klass()) {
classloader2 = InstanceKlass::cast(class2)->class_loader();
classloader2 = class2->class_loader();
classpkg2 = InstanceKlass::cast(class2)->package();
} else {
assert(class2->is_typeArray_klass(), "should be type array");
classloader2 = NULL;
classpkg2 = NULL;
}
const Symbol* classname2 = class2->name();
return InstanceKlass::is_same_class_package(classloader1, classname1,
classloader2, classname2);
// Same package is determined by comparing class loader
// and package entries. Both must be the same. This rule
// applies even to classes that are defined in the unnamed
// package, they still must have the same class loader.
if ((classloader1 == classloader2) && (classpkg1 == classpkg2)) {
return true;
}
return false;
}
bool InstanceKlass::is_same_class_package(oop other_class_loader,
@ -2225,43 +2335,24 @@ bool InstanceKlass::is_same_class_package(oop class_loader1, const Symbol* class
// The Symbol*'s are in UTF8 encoding. Since we only need to check explicitly
// for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
// Otherwise, we just compare jbyte values between the strings.
const jbyte *name1 = class_name1->base();
const jbyte *name2 = class_name2->base();
int length1 = 0;
int length2 = 0;
const jbyte *name1 = package_from_name(class_name1, length1);
const jbyte *name2 = package_from_name(class_name2, length2);
const jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
if ((length1 < 0) || (length2 < 0)) {
// error occurred parsing package name.
return false;
}
if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
if ((name1 == NULL) || (name2 == NULL)) {
// One of the two doesn't have a package. Only return true
// if the other one also doesn't have a package.
return last_slash1 == last_slash2;
} else {
// Skip over '['s
if (*name1 == '[') {
do {
name1++;
} while (*name1 == '[');
if (*name1 != 'L') {
// Something is terribly wrong. Shouldn't be here.
return false;
}
}
if (*name2 == '[') {
do {
name2++;
} while (*name2 == '[');
if (*name2 != 'L') {
// Something is terribly wrong. Shouldn't be here.
return false;
}
}
// Check that package part is identical
int length1 = last_slash1 - name1;
int length2 = last_slash2 - name2;
return UTF8::equal(name1, length1, name2, length2);
return name1 == name2;
}
// Check that package part is identical
return UTF8::equal(name1, length1, name2, length2);
}
}
@ -2300,7 +2391,7 @@ bool InstanceKlass::is_same_package_member_impl(const InstanceKlass* class1,
if (!class2->is_instance_klass()) return false;
// must be in same package before we try anything else
if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
if (!class1->is_same_class_package(class2))
return false;
// As long as there is an outer1.getEnclosingClass,
@ -2908,6 +2999,7 @@ const char* InstanceKlass::internal_name() const {
void InstanceKlass::print_loading_log(LogLevel::type type,
ClassLoaderData* loader_data,
const char* module_name,
const ClassFileStream* cfs) const {
ResourceMark rm;
outputStream* log;
@ -2928,7 +3020,11 @@ void InstanceKlass::print_loading_log(LogLevel::type type,
// Source
if (cfs != NULL) {
if (cfs->source() != NULL) {
log->print(" source: %s", cfs->source());
if (module_name != NULL) {
log->print(" source: jrt:/%s", module_name);
} else {
log->print(" source: %s", cfs->source());
}
} else if (loader_data == ClassLoaderData::the_null_class_loader_data()) {
Thread* THREAD = Thread::current();
Klass* caller =