--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Mar 24 11:50:51 2016 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Mar 24 16:21:18 2016 +0100
@@ -32,6 +32,7 @@
#include "classfile/javaClasses.inline.hpp"
#include "classfile/klassFactory.hpp"
#include "classfile/loaderConstraints.hpp"
+#include "classfile/packageEntry.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/resolutionErrors.hpp"
#include "classfile/stringTable.hpp"
@@ -51,6 +52,7 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
#include "prims/jvmtiEnvBase.hpp"
#include "prims/methodHandles.hpp"
@@ -171,13 +173,13 @@
}
/**
- * Returns true if the passed class loader is the extension class loader.
+ * Returns true if the passed class loader is the platform class loader.
*/
-bool SystemDictionary::is_ext_class_loader(Handle class_loader) {
+bool SystemDictionary::is_platform_class_loader(Handle class_loader) {
if (class_loader.is_null()) {
return false;
}
- return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
+ return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass());
}
// ----------------------------------------------------------------------------
@@ -1144,6 +1146,7 @@
const char* pkg = "java/";
if (!HAS_PENDING_EXCEPTION &&
!class_loader.is_null() &&
+ !SystemDictionary::is_platform_class_loader(class_loader) &&
parsed_name != NULL &&
!strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
// It is illegal to define classes in the "java." package from
@@ -1236,13 +1239,88 @@
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
// Make sure we only return the boot class for the NULL classloader.
if (ik.not_null() &&
- SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) {
+ ik->is_shared_boot_class() && class_loader.is_null()) {
Handle protection_domain;
return load_shared_class(ik, class_loader, protection_domain, THREAD);
}
return instanceKlassHandle();
}
+// Check if a shared class can be loaded by the specific classloader:
+//
+// NULL classloader:
+// - Module class from "modules" jimage. ModuleEntry must be defined in the classloader.
+// - Class from -Xbootclasspath/a. The class has no defined PackageEntry, or must
+// be defined in an unnamed module.
+bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
+ instanceKlassHandle ik,
+ Handle class_loader, TRAPS) {
+ int path_index = ik->shared_classpath_index();
+ SharedClassPathEntry* ent =
+ (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+ if (!Universe::is_module_initialized()) {
+ assert(ent->is_jrt(),
+ "Loading non-bootstrap classes before the module system is initialized");
+ assert(class_loader.is_null(), "sanity");
+ return true;
+ }
+ // Get the pkg_entry from the classloader
+ TempNewSymbol pkg_name = NULL;
+ PackageEntry* pkg_entry = NULL;
+ ModuleEntry* mod_entry = NULL;
+ int length = 0;
+ ClassLoaderData* loader_data = class_loader_data(class_loader);
+ const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+ if (pkg_string != NULL) {
+ pkg_name = SymbolTable::new_symbol((const char*)pkg_string,
+ length, CHECK_(false));
+ if (loader_data != NULL) {
+ pkg_entry = loader_data->packages()->lookup_only(pkg_name);
+ }
+ if (pkg_entry != NULL) {
+ mod_entry = pkg_entry->module();
+ }
+ }
+
+ if (class_loader.is_null()) {
+ // The NULL classloader can load archived class originated from the
+ // "modules" jimage and the -Xbootclasspath/a. For class from the
+ // "modules" jimage, the PackageEntry/ModuleEntry must be defined
+ // by the NULL classloader.
+ if (mod_entry != NULL) {
+ // PackageEntry/ModuleEntry is found in the classloader. Check if the
+ // ModuleEntry's location agrees with the archived class' origination.
+ if (ent->is_jrt() && mod_entry->location()->starts_with("jrt:")) {
+ return true; // Module class from the "module" jimage
+ }
+ }
+
+ // If the archived class is not from the "module" jimage, the class can be
+ // loaded by the NULL classloader if
+ //
+ // 1. the class is from the unamed package
+ // 2. or, the class is not from a module defined in the NULL classloader
+ // 3. or, the class is from an unamed module
+ if (!ent->is_jrt() && ik->is_shared_boot_class()) {
+ // the class is from the -Xbootclasspath/a
+ if (pkg_string == NULL ||
+ pkg_entry == NULL ||
+ pkg_entry->in_unnamed_module()) {
+ assert(mod_entry == NULL ||
+ mod_entry == loader_data->modules()->unnamed_module(),
+ "the unnamed module is not defined in the classloader");
+ return true;
+ }
+ }
+ return false;
+ } else {
+ bool res = SystemDictionaryShared::is_shared_class_visible_for_classloader(
+ ik, class_loader, pkg_string, pkg_name,
+ pkg_entry, mod_entry, CHECK_(false));
+ return res;
+ }
+}
+
instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
Handle class_loader,
Handle protection_domain, TRAPS) {
@@ -1250,6 +1328,12 @@
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
Symbol* class_name = ik->name();
+ bool visible = is_shared_class_visible(
+ class_name, ik, class_loader, CHECK_(nh));
+ if (!visible) {
+ return nh;
+ }
+
// Found the class, now load the superclass and interfaces. If they
// are shared, add them to the main system dictionary and reset
// their hierarchy references (supers, subs, and interfaces).
@@ -1303,12 +1387,20 @@
}
if (log_is_enabled(Info, classload)) {
- ik()->print_loading_log(LogLevel::Info, loader_data, NULL);
+ ik()->print_loading_log(LogLevel::Info, loader_data, NULL, NULL);
}
// No 'else' here as logging levels are not mutually exclusive
if (log_is_enabled(Debug, classload)) {
- ik()->print_loading_log(LogLevel::Debug, loader_data, NULL);
+ ik()->print_loading_log(LogLevel::Debug, loader_data, NULL, NULL);
+ }
+
+ // For boot loader, ensure that GetSystemPackage knows that a class in this
+ // package was loaded.
+ if (class_loader.is_null()) {
+ int path_index = ik->shared_classpath_index();
+ ResourceMark rm;
+ ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
}
if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
@@ -1329,7 +1421,68 @@
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
+
if (class_loader.is_null()) {
+ int length = 0;
+ PackageEntry* pkg_entry = NULL;
+ bool search_only_bootloader_append = false;
+ ClassLoaderData *loader_data = class_loader_data(class_loader);
+
+ // Find the package in the boot loader's package entry table.
+ const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+ if (pkg_string != NULL) {
+ TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, CHECK_(nh));
+ pkg_entry = loader_data->packages()->lookup_only(pkg_name);
+ }
+
+ // Prior to attempting to load the class, enforce the boot loader's
+ // visibility boundaries.
+ if (!Universe::is_module_initialized()) {
+ // During bootstrapping, prior to module initialization, any
+ // class attempting to be loaded must be checked against the
+ // java.base packages in the boot loader's PackageEntryTable.
+ // No class outside of java.base is allowed to be loaded during
+ // this bootstrapping window.
+ if (!DumpSharedSpaces) {
+ if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
+ // Class is either in the unnamed package or in
+ // a named package within the unnamed module. Either
+ // case is outside of java.base, do not attempt to
+ // load the class post java.base definition. If
+ // java.base has not been defined, let the class load
+ // and its package will be checked later by
+ // ModuleEntryTable::verify_javabase_packages.
+ if (ModuleEntryTable::javabase_defined()) {
+ return nh;
+ }
+ } else {
+ // Check that the class' package is defined within java.base.
+ ModuleEntry* mod_entry = pkg_entry->module();
+ Symbol* mod_entry_name = mod_entry->name();
+ if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) {
+ return nh;
+ }
+ }
+ }
+ } else {
+ assert(!DumpSharedSpaces, "Archive dumped after module system initialization");
+ // After the module system has been initialized, check if the class'
+ // package is in a module defined to the boot loader.
+ if (pkg_string == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
+ // Class is either in the unnamed package, in a named package
+ // within a module not defined to the boot loader or in a
+ // a named package within the unnamed module. In all cases,
+ // limit visibility to search for the class only in the boot
+ // loader's append path.
+ search_only_bootloader_append = true;
+ }
+ }
+
+ // Prior to bootstrapping's module initialization, never load a class outside
+ // of the boot loader's module path
+ assert(Universe::is_module_initialized() || DumpSharedSpaces ||
+ !search_only_bootloader_append,
+ "Attempt to load a class outside of boot loader's module path");
// Search the shared system dictionary for classes preloaded into the
// shared spaces.
@@ -1344,7 +1497,7 @@
if (k.is_null()) {
// Use VM class loader
PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
- k = ClassLoader::load_class(class_name, CHECK_(nh));
+ k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_(nh));
}
// find_or_define_instance_class may return a different InstanceKlass
@@ -1669,7 +1822,7 @@
}
-// Get the next class in the diictionary.
+// Get the next class in the dictionary.
Klass* SystemDictionary::try_get_next_class() {
return dictionary()->try_get_next_class();
}
@@ -1940,6 +2093,11 @@
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
+
+ // Create the ModuleEntry for java.base. This call needs to be done here,
+ // after vmSymbols::initialize() is called but before any classes are pre-loaded.
+ ClassLoader::create_javabase();
+
// Preload commonly used klasses
WKID scan = FIRST_WKID;
// first do Object, then String, Class