--- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri May 06 06:23:29 2016 -0700
@@ -140,9 +140,10 @@
PerfCounter* ClassLoader::_isUnsyncloadClass = NULL;
PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
-ClassPathEntry* ClassLoader::_first_entry = NULL;
-ClassPathEntry* ClassLoader::_last_entry = NULL;
-int ClassLoader::_num_entries = 0;
+GrowableArray<ModuleClassPathList*>* ClassLoader::_xpatch_entries = NULL;
+ClassPathEntry* ClassLoader::_first_entry = NULL;
+ClassPathEntry* ClassLoader::_last_entry = NULL;
+int ClassLoader::_num_entries = 0;
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
bool ClassLoader::_has_jimage = false;
#if INCLUDE_CDS
@@ -179,6 +180,44 @@
return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
}
+// Used to obtain the package name from a fully qualified class name.
+// It is the responsibility of the caller to establish ResourceMark.
+const char* ClassLoader::package_from_name(const char* class_name) {
+ const char* last_slash = strrchr(class_name, '/');
+ if (last_slash == NULL) {
+ // No package name
+ return NULL;
+ }
+ int length = last_slash - class_name;
+
+ // A class name could have just the slash character in the name,
+ // resulting in a negative length.
+ if (length <= 0) {
+ // No package name
+ 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, length);
+ *(pkg_name+length) = '\0';
+
+ return (const char *)pkg_name;
+}
+
+// Given a fully qualified class name, find its defining package in the class loader's
+// package entry table.
+static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
+ ResourceMark rm(THREAD);
+ const char *pkg_name = ClassLoader::package_from_name(class_name);
+ if (pkg_name == NULL) {
+ return NULL;
+ }
+ PackageEntryTable* pkgEntryTable = loader_data->packages();
+ TempNewSymbol pkg_symbol = SymbolTable::new_symbol(pkg_name, CHECK_NULL);
+ return pkgEntryTable->lookup_only(pkg_symbol);
+}
ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
@@ -281,8 +320,7 @@
#if INCLUDE_CDS
u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TRAPS) {
u1* buffer = NULL;
- if (!_is_boot_append) {
- assert(DumpSharedSpaces, "Should be called only for non-boot entries during dump time");
+ if (DumpSharedSpaces) {
// We presume default is multi-release enabled
const char* multi_ver = Arguments::get_property("jdk.util.jar.enableMultiRelease");
const char* verstr = Arguments::get_property("jdk.util.jar.version");
@@ -402,31 +440,6 @@
}
}
-void ClassPathImageEntry::name_to_package(const char* name, char* buffer, int length) {
- const char *pslash = strrchr(name, '/');
- if (pslash == NULL) {
- buffer[0] = '\0';
- return;
- }
- int len = pslash - name;
-#if INCLUDE_CDS
- if (len <= 0 && DumpSharedSpaces) {
- buffer[0] = '\0';
- return;
- }
-#endif
- assert(len > 0, "Bad length for package name");
- if (len >= length) {
- buffer[0] = '\0';
- return;
- }
- // drop name after last slash (including slash)
- // Ex., "java/lang/String.class" => "java/lang"
- strncpy(buffer, name, len);
- // ensure string termination (strncpy does not guarantee)
- buffer[len] = '\0';
-}
-
// For a class in a named module, look it up in the jimage file using this syntax:
// /<module-name>/<package-name>/<base-class>
//
@@ -439,15 +452,10 @@
JImageLocationRef location = (*JImageFindResource)(_jimage, "", get_jimage_version_string(), name, &size);
if (location == 0) {
- char package[JIMAGE_MAX_PATH];
- name_to_package(name, package, JIMAGE_MAX_PATH);
+ ResourceMark rm;
+ const char* pkg_name = ClassLoader::package_from_name(name);
-#if INCLUDE_CDS
- if (package[0] == '\0' && DumpSharedSpaces) {
- return NULL;
- }
-#endif
- if (package[0] != '\0') {
+ if (pkg_name != NULL) {
if (!Universe::is_module_initialized()) {
location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
#if INCLUDE_CDS
@@ -455,7 +463,7 @@
// modules defined for other class loaders. So, for now, get their module
// names from the "modules" jimage file.
if (DumpSharedSpaces && location == 0) {
- const char* module_name = (*JImagePackageToModule)(_jimage, package);
+ const char* module_name = (*JImagePackageToModule)(_jimage, pkg_name);
if (module_name != NULL) {
location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
}
@@ -463,13 +471,7 @@
#endif
} else {
- // Get boot class loader's package entry table
- PackageEntryTable* pkgEntryTable =
- ClassLoaderData::the_null_class_loader_data()->packages();
- // Get package's package entry
- TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package, CHECK_NULL);
- PackageEntry* package_entry = pkgEntryTable->lookup_only(pkg_symbol);
-
+ PackageEntry* package_entry = get_package_entry(name, ClassLoaderData::the_null_class_loader_data(), THREAD);
if (package_entry != NULL) {
ResourceMark rm;
// Get the module name
@@ -542,6 +544,33 @@
}
#endif
+ModuleClassPathList::ModuleClassPathList(Symbol* module_name) {
+ _module_name = module_name;
+ _module_first_entry = NULL;
+ _module_last_entry = NULL;
+}
+
+ModuleClassPathList::~ModuleClassPathList() {
+ // Clean out each ClassPathEntry on list
+ ClassPathEntry* e = _module_first_entry;
+ while (e != NULL) {
+ ClassPathEntry* next_entry = e->next();
+ delete e;
+ e = next_entry;
+ }
+}
+
+void ModuleClassPathList::add_to_list(ClassPathEntry* new_entry) {
+ if (new_entry != NULL) {
+ if (_module_last_entry == NULL) {
+ _module_first_entry = _module_last_entry = new_entry;
+ } else {
+ _module_last_entry->set_next(new_entry);
+ _module_last_entry = new_entry;
+ }
+ }
+}
+
void ClassLoader::trace_class_path(const char* msg, const char* name) {
if (log_is_enabled(Info, class, path)) {
ResourceMark rm;
@@ -619,6 +648,61 @@
}
#endif
+// Construct the array of module/path pairs as specified to -Xpatch
+// for the boot loader to search ahead of the jimage, if the class being
+// loaded is defined to a module that has been specified to -Xpatch.
+void ClassLoader::setup_xpatch_entries() {
+ Thread* THREAD = Thread::current();
+ GrowableArray<ModuleXPatchPath*>* xpatch_args = Arguments::get_xpatchprefix();
+ int num_of_entries = xpatch_args->length();
+
+ // Set up the boot loader's xpatch_entries list
+ _xpatch_entries = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<ModuleClassPathList*>(num_of_entries, true);
+
+ for (int i = 0; i < num_of_entries; i++) {
+ const char* module_name = (xpatch_args->at(i))->module_name();
+ Symbol* const module_sym = SymbolTable::lookup(module_name, (int)strlen(module_name), CHECK);
+ assert(module_sym != NULL, "Failed to obtain Symbol for module name");
+ ModuleClassPathList* module_cpl = new ModuleClassPathList(module_sym);
+
+ char* class_path = (xpatch_args->at(i))->path_string();
+ int len = (int)strlen(class_path);
+ int end = 0;
+ // Iterate over the module's class path entries
+ for (int start = 0; start < len; start = end) {
+ while (class_path[end] && class_path[end] != os::path_separator()[0]) {
+ end++;
+ }
+ EXCEPTION_MARK;
+ ResourceMark rm(THREAD);
+ char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
+ strncpy(path, &class_path[start], end - start);
+ path[end - start] = '\0';
+
+ struct stat st;
+ if (os::stat(path, &st) == 0) {
+ // File or directory found
+ Thread* THREAD = Thread::current();
+ ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
+ // If the path specification is valid, enter it into this module's list
+ if (new_entry != NULL) {
+ module_cpl->add_to_list(new_entry);
+ }
+ }
+
+ while (class_path[end] == os::path_separator()[0]) {
+ end++;
+ }
+ }
+
+ // Record the module into the list of -Xpatch entries only if
+ // valid ClassPathEntrys have been created
+ if (module_cpl->module_first_entry() != NULL) {
+ _xpatch_entries->push(module_cpl);
+ }
+ }
+}
+
void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) {
int offset = 0;
int len = (int)strlen(class_path);
@@ -850,8 +934,29 @@
}
void ClassLoader::print_bootclasspath() {
- ClassPathEntry* e = _first_entry;
+ ClassPathEntry* e;
tty->print("[bootclasspath= ");
+
+ // Print -Xpatch module/path specifications first
+ if (_xpatch_entries != NULL) {
+ ResourceMark rm;
+ int num_of_entries = _xpatch_entries->length();
+ for (int i = 0; i < num_of_entries; i++) {
+ ModuleClassPathList* mpl = _xpatch_entries->at(i);
+ tty->print("%s=", mpl->module_name()->as_C_string());
+ e = mpl->module_first_entry();
+ while (e != NULL) {
+ tty->print("%s", e->name());
+ e = e->next();
+ if (e != NULL) {
+ tty->print("%s", os::path_separator());
+ }
+ }
+ tty->print(" ;");
+ }
+ }
+
+ e = _first_entry;
while (e != NULL) {
tty->print("%s ;", e->name());
e = e->next();
@@ -945,6 +1050,7 @@
return; // only needed for CDS dump time
}
+ ResourceMark rm;
jlong size;
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
if (location == 0) {
@@ -989,7 +1095,6 @@
begin_ptr = ++end_ptr;
end_ptr = strchr(begin_ptr, '\n');
}
- FREE_RESOURCE_ARRAY(u1, buffer, size);
}
#endif
@@ -1110,8 +1215,7 @@
return APP_LOADER;
}
-s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e,
- int classpath_index, TRAPS) {
+s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e, int classpath_index, TRAPS) {
assert(DumpSharedSpaces, "Only used for CDS dump time");
// obtain the classloader type based on the class name.
@@ -1160,12 +1264,11 @@
}
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
-
assert(name != NULL, "invariant");
assert(THREAD->is_Java_thread(), "must be a JavaThread");
- ResourceMark rm;
- HandleMark hm;
+ ResourceMark rm(THREAD);
+ HandleMark hm(THREAD);
const char* const class_name = name->as_C_string();
@@ -1181,30 +1284,101 @@
// Lookup stream for parsing .class file
ClassFileStream* stream = NULL;
s2 classpath_index = 0;
+ ClassPathEntry* e = NULL;
// If DumpSharedSpaces is true, boot loader visibility boundaries are set
- // to be _first_entry to the end (all path entries).
+ // to be _first_entry to the end (all path entries). No -Xpatch entries are
+ // included since CDS and AppCDS are not supported if -Xpatch is specified.
//
// If search_append_only is true, boot loader visibility boundaries are
- // set to be _fist_append_entry to the end. This includes:
+ // set to be _first_append_entry to the end. This includes:
// [-Xbootclasspath/a]; [jvmti appended entries]
//
// If both DumpSharedSpaces and search_append_only are false, boot loader
// visibility boundaries are set to be _first_entry to the entry before
// the _first_append_entry. This would include:
- // [-Xpatch:<dirs>]; [exploded build | modules]
+ // [-Xpatch:<module>=<file>(<pathsep><file>)*]; [exploded build | jimage]
//
// DumpSharedSpaces and search_append_only are mutually exclusive and cannot
// be true at the same time.
- ClassPathEntry* e = (search_append_only ? _first_append_entry : _first_entry);
- ClassPathEntry* last_e =
- (search_append_only || DumpSharedSpaces ? NULL : _first_append_entry);
+ assert(!(DumpSharedSpaces && search_append_only), "DumpSharedSpaces and search_append_only are both true");
+
+ // Load Attempt #1: -Xpatch
+ // Determine the class' defining module. If it appears in the _xpatch_entries,
+ // attempt to load the class from those locations specific to the module.
+ // Note: The -Xpatch entries are never searched if the boot loader's
+ // visibility boundary is limited to only searching the append entries.
+ if (_xpatch_entries != NULL && !search_append_only && !DumpSharedSpaces) {
+ // Find the module in the boot loader's module entry table
+ PackageEntry* pkg_entry = get_package_entry(class_name, ClassLoaderData::the_null_class_loader_data(), THREAD);
+ ModuleEntry* mod_entry = (pkg_entry != NULL) ? pkg_entry->module() : NULL;
+
+ // If the module system has not defined java.base yet, then
+ // classes loaded are assumed to be defined to java.base.
+ // When java.base is eventually defined by the module system,
+ // all packages of classes that have been previously loaded
+ // are verified in ModuleEntryTable::verify_javabase_packages().
+ if (!Universe::is_module_initialized() &&
+ !ModuleEntryTable::javabase_defined() &&
+ mod_entry == NULL) {
+ mod_entry = ModuleEntryTable::javabase_module();
+ }
+
+ // The module must be a named module
+ if (mod_entry != NULL && mod_entry->is_named()) {
+ int num_of_entries = _xpatch_entries->length();
+ const Symbol* class_module_name = mod_entry->name();
+
+ // Loop through all the xpatch entries looking for module
+ for (int i = 0; i < num_of_entries; i++) {
+ ModuleClassPathList* module_cpl = _xpatch_entries->at(i);
+ Symbol* module_cpl_name = module_cpl->module_name();
- {
+ if (module_cpl_name->fast_compare(class_module_name) == 0) {
+ // Class' module has been located, attempt to load
+ // the class from the module's ClassPathEntry list.
+ e = module_cpl->module_first_entry();
+ while (e != NULL) {
+ stream = e->open_stream(file_name, CHECK_NULL);
+ // No context.check is required since both CDS
+ // and AppCDS are turned off if -Xpatch is specified.
+ if (NULL != stream) {
+ break;
+ }
+ e = e->next();
+ }
+ // If the module was located in the xpatch entries, break out
+ // even if the class was not located successfully from that module's
+ // ClassPathEntry list. There will not be another valid entry for
+ // that module in the _xpatch_entries array.
+ break;
+ }
+ }
+ }
+ }
+
+ // Load Attempt #2: [exploded build | jimage]
+ if (!search_append_only && (NULL == stream)) {
+ e = _first_entry;
+ while ((e != NULL) && (e != _first_append_entry)) {
+ stream = e->open_stream(file_name, CHECK_NULL);
+ if (!context.check(stream, classpath_index)) {
+ return NULL;
+ }
+ if (NULL != stream) {
+ break;
+ }
+ e = e->next();
+ ++classpath_index;
+ }
+ }
+
+ // Load Attempt #3: [-Xbootclasspath/a]; [jvmti appended entries]
+ if ((search_append_only || DumpSharedSpaces) && (NULL == stream)) {
+ // For the boot loader append path search, must calculate
+ // the starting classpath_index prior to attempting to
+ // load the classfile.
if (search_append_only) {
- // For the boot loader append path search, must calculate
- // the starting classpath_index prior to attempting to
- // load the classfile.
ClassPathEntry *tmp_e = _first_entry;
while ((tmp_e != NULL) && (tmp_e != _first_append_entry)) {
tmp_e = tmp_e->next();
@@ -1212,11 +1386,8 @@
}
}
- // Attempt to load the classfile from either:
- // - [-Xpatch:dir]; exploded build | modules
- // or
- // - [-Xbootclasspath/a]; [jvmti appended entries]
- while ((e != NULL) && (e != last_e)) {
+ e = _first_append_entry;
+ while (e != NULL) {
stream = e->open_stream(file_name, CHECK_NULL);
if (!context.check(stream, classpath_index)) {
return NULL;
@@ -1386,10 +1557,23 @@
}
-void classLoader_init() {
+void classLoader_init1() {
ClassLoader::initialize();
}
+// Complete the ClassPathEntry setup for the boot loader
+void classLoader_init2() {
+ // Setup the list of module/path pairs for -Xpatch processing
+ // This must be done after the SymbolTable is created in order
+ // to use fast_compare on module names instead of a string compare.
+ if (Arguments::get_xpatchprefix() != NULL) {
+ ClassLoader::setup_xpatch_entries();
+ }
+
+ // Determine if this is an exploded build
+ ClassLoader::set_has_jimage();
+}
+
bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
assert(orig != NULL && out != NULL && len > 0, "bad arguments");
@@ -1433,17 +1617,19 @@
}
ModuleEntryTable::set_javabase_module(jb_module);
}
+}
- // When looking for the jimage file, only
- // search the boot loader's module path which
- // can consist of [-Xpatch]; exploded build | modules
- // Do not search the boot loader's append path.
+void ClassLoader::set_has_jimage() {
+ // Determine if this is an exploded build. When looking for
+ // the jimage file, only search the piece of the boot
+ // loader's boot class path which contains [exploded build | jimage].
+ // Do not search the boot loader's xpatch entries or append path.
ClassPathEntry* e = _first_entry;
ClassPathEntry* last_e = _first_append_entry;
while ((e != NULL) && (e != last_e)) {
JImageFile *jimage = e->jimage();
if (jimage != NULL && e->is_jrt()) {
- set_has_jimage(true);
+ _has_jimage = true;
#if INCLUDE_CDS
ClassLoader::initialize_module_loader_map(jimage);
#endif
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp Fri May 06 06:23:29 2016 -0700
@@ -142,13 +142,30 @@
JImageFile* jimage() const { return _jimage; }
ClassPathImageEntry(JImageFile* jimage, const char* name);
~ClassPathImageEntry();
- void name_to_package(const char* name, char* package, int length);
ClassFileStream* open_stream(const char* name, TRAPS);
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
};
+// ModuleClassPathList contains a linked list of ClassPathEntry's
+// that have been specified for a specific module. Currently,
+// the only way to specify a module/path pair is via the -Xpatch
+// command line option.
+class ModuleClassPathList : public CHeapObj<mtClass> {
+private:
+ Symbol* _module_name;
+ // First and last entries of class path entries for a specific module
+ ClassPathEntry* _module_first_entry;
+ ClassPathEntry* _module_last_entry;
+public:
+ Symbol* module_name() const { return _module_name; }
+ ClassPathEntry* module_first_entry() const { return _module_first_entry; }
+ ModuleClassPathList(Symbol* module_name);
+ ~ModuleClassPathList();
+ void add_to_list(ClassPathEntry* new_entry);
+};
+
class SharedPathsMiscInfo;
class ClassLoader: AllStatic {
@@ -195,21 +212,31 @@
static PerfCounter* _isUnsyncloadClass;
static PerfCounter* _load_instance_class_failCounter;
- // First entry in linked list of ClassPathEntry instances.
- // This consists of entries made up by:
- // - boot loader modules
- // [-Xpatch]; exploded build | modules;
- // - boot loader append path
- // [-Xbootclasspath/a]; [jvmti appended entries]
+ // The boot class path consists of 3 ordered pieces:
+ // 1. the module/path pairs specified to -Xpatch
+ // -Xpatch:<module>=<file>(<pathsep><file>)*
+ // 2. the base piece
+ // [exploded build | jimage]
+ // 3. boot loader append path
+ // [-Xbootclasspath/a]; [jvmti appended entries]
+ //
+ // The boot loader must obey this order when attempting
+ // to load a class.
+
+ // Contains the module/path pairs specified to -Xpatch
+ static GrowableArray<ModuleClassPathList*>* _xpatch_entries;
+
+ // Contains the ClassPathEntry instances that include
+ // both the base piece and the boot loader append path.
static ClassPathEntry* _first_entry;
// Last entry in linked list of ClassPathEntry instances
static ClassPathEntry* _last_entry;
static int _num_entries;
- // Pointer into the linked list of ClassPathEntry instances.
// Marks the start of:
// - the boot loader's append path
// [-Xbootclasspath/a]; [jvmti appended entries]
+ // within the linked list of ClassPathEntry instances.
static ClassPathEntry* _first_append_entry;
static const char* _shared_archive;
@@ -325,11 +352,11 @@
return _load_instance_class_failCounter;
}
+ // Set up the module/path pairs as specified to -Xpatch
+ static void setup_xpatch_entries();
+
// Sets _has_jimage to TRUE if "modules" jimage file exists
- static void set_has_jimage(bool val) {
- _has_jimage = val;
- }
-
+ static void set_has_jimage();
static bool has_jimage() { return _has_jimage; }
// Create the ModuleEntry for java.base
@@ -416,6 +443,9 @@
static bool string_ends_with(const char* str, const char* str_to_find);
+ // obtain package name from a fully qualified class name
+ static const char* package_from_name(const char* class_name);
+
static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
// Debugging
--- a/hotspot/src/share/vm/classfile/modules.cpp Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/src/share/vm/classfile/modules.cpp Fri May 06 06:23:29 2016 -0700
@@ -133,68 +133,31 @@
return NULL;
}
-// Check if -Xpatch:<dirs> was specified. If so, prepend each <dir>/module_name,
-// if it exists, to bootpath so boot loader can find the class files. Also, if
-// using exploded modules, append <java.home>/modules/module_name, if it exists,
-// to bootpath so that its class files can be found by the boot loader.
-static void add_to_boot_loader_list(char *module_name, TRAPS) {
- // java.base should be handled by argument parsing.
+// If using exploded build, append <java.home>/modules/module_name, if it exists,
+// to the system boot class path in order for the boot loader to locate class files.
+static void add_to_exploded_build_list(char *module_name, TRAPS) {
+ assert(!ClassLoader::has_jimage(), "Exploded build not applicable");
+ // java.base is handled by os::set_boot_path
assert(strcmp(module_name, "java.base") != 0, "Unexpected java.base module name");
+
char file_sep = os::file_separator()[0];
size_t module_len = strlen(module_name);
- // If -Xpatch is set then add <patch-dir>/module_name paths.
- char** patch_dirs = Arguments::patch_dirs();
- if (patch_dirs != NULL) {
- int dir_count = Arguments::patch_dirs_count();
- for (int x = 0; x < dir_count; x++) {
- // Really shouldn't be NULL, but check can't hurt
- if (patch_dirs[x] != NULL) {
- size_t len = strlen(patch_dirs[x]);
- if (len != 0) { // Ignore empty strings.
- len = len + module_len + 2;
- char* prefix_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
- jio_snprintf(prefix_path, len, "%s%c%s", patch_dirs[x], file_sep, module_name);
-
- // See if Xpatch module path exists.
- struct stat st;
- if ((os::stat(prefix_path, &st) != 0)) {
- FREE_C_HEAP_ARRAY(char, prefix_path);
- } else {
- {
- HandleMark hm;
- Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
- ObjectLocker ol(loader_lock, THREAD);
- ClassLoader::prepend_to_list(prefix_path);
- }
- log_info(class, load)("opened: -Xpatch %s", prefix_path);
- }
- }
- }
- }
- }
-
- // If "modules" jimage does not exist then assume exploded form
- // ${java.home}/modules/<module-name>
- char* path = NULL;
- if (!ClassLoader::has_jimage()) {
- const char* home = Arguments::get_java_home();
- size_t len = strlen(home) + module_len + 32;
- path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
- jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
- struct stat st;
- // See if exploded module path exists.
- if ((os::stat(path, &st) != 0)) {
- FREE_C_HEAP_ARRAY(char, path);
- path = NULL;
- }
+ const char* home = Arguments::get_java_home();
+ size_t len = strlen(home) + module_len + 32;
+ char* path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+ jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
+ struct stat st;
+ // See if exploded module path exists
+ if ((os::stat(path, &st) != 0)) {
+ FREE_C_HEAP_ARRAY(char, path);
+ path = NULL;
}
if (path != NULL) {
HandleMark hm;
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
ObjectLocker ol(loader_lock, THREAD);
-
log_info(class, load)("opened: %s", path);
ClassLoader::add_to_list(path);
}
@@ -498,13 +461,12 @@
}
}
- if (loader == NULL && !Universe::is_module_initialized()) {
- // Now that the module is defined, if it is in the bootloader, make sure that
- // its classes can be found. Check if -Xpatch:<path> was specified. If
- // so prepend <path>/module_name, if it exists, to bootpath. Also, if using
- // exploded modules, prepend <java.home>/modules/module_name, if it exists,
- // to bootpath.
- add_to_boot_loader_list(module_name, CHECK);
+ // If the module is defined to the boot loader and an exploded build is being
+ // used, prepend <java.home>/modules/modules_name, if it exists, to the system boot class path.
+ if (loader == NULL &&
+ !Universe::is_module_initialized() &&
+ !ClassLoader::has_jimage()) {
+ add_to_exploded_build_list(module_name, CHECK);
}
}
--- a/hotspot/src/share/vm/memory/filemap.cpp Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/src/share/vm/memory/filemap.cpp Fri May 06 06:23:29 2016 -0700
@@ -881,7 +881,7 @@
return false;
}
- if (Arguments::patch_dirs() != NULL) {
+ if (Arguments::get_xpatchprefix() != NULL) {
FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
return false;
}
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri May 06 06:23:29 2016 -0700
@@ -84,8 +84,6 @@
const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER;
int Arguments::_sun_java_launcher_pid = -1;
bool Arguments::_sun_java_launcher_is_altjvm = false;
-int Arguments::_patch_dirs_count = 0;
-char** Arguments::_patch_dirs = NULL;
int Arguments::_bootclassloader_append_index = -1;
// These parameters are reset in method parse_vm_init_args()
@@ -112,6 +110,7 @@
SystemProperty *Arguments::_java_class_path = NULL;
SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
+GrowableArray<ModuleXPatchPath*> *Arguments::_xpatchprefix = NULL;
PathString *Arguments::_system_boot_class_path = NULL;
char* Arguments::_ext_dirs = NULL;
@@ -580,204 +579,6 @@
}
#endif
-// Constructs the system boot class path from the following components, in order:
-//
-// prefix // from -Xpatch:...
-// base // from os::get_system_properties()
-// suffix // from -Xbootclasspath/a:...
-//
-// This could be AllStatic, but it isn't needed after argument processing is
-// complete. After argument processing, the combined components are copied
-// to Arguments::_system_boot_class_path via a call to Arguments::set_sysclasspath.
-class ArgumentBootClassPath: public StackObj {
-public:
- ArgumentBootClassPath(const char* base);
- ~ArgumentBootClassPath();
-
- inline void set_base(const char* base);
- inline void add_prefix(const char* prefix);
- inline void add_suffix_to_prefix(const char* suffix);
- inline void add_suffix(const char* suffix);
- inline void reset_path(const char* base);
-
- inline const char* get_base() const { return _items[_bcp_base]; }
- inline const char* get_prefix() const { return _items[_bcp_prefix]; }
- inline const char* get_suffix() const { return _items[_bcp_suffix]; }
-
- // Combine all the components into a single c-heap-allocated string; caller
- // must free the string if/when no longer needed.
- char* combined_path();
-
-private:
- // Utility routines.
- static char* add_to_path(const char* path, const char* str, bool prepend);
- static char* add_jars_to_path(char* path, const char* directory);
-
- inline void reset_item_at(int index);
-
- // Array indices for the items that make up the sysclasspath. All except the
- // base are allocated in the C heap and freed by this class.
- enum {
- _bcp_prefix, // was -Xpatch:...
- _bcp_base, // the default system boot class path
- _bcp_suffix, // from -Xbootclasspath/a:...
- _bcp_nitems // the number of items, must be last.
- };
-
- const char* _items[_bcp_nitems];
-};
-
-ArgumentBootClassPath::ArgumentBootClassPath(const char* base) {
- memset(_items, 0, sizeof(_items));
- _items[_bcp_base] = base;
-}
-
-ArgumentBootClassPath::~ArgumentBootClassPath() {
- // Free everything except the base.
- for (int i = 0; i < _bcp_nitems; ++i) {
- if (i != _bcp_base) reset_item_at(i);
- }
-}
-
-inline void ArgumentBootClassPath::set_base(const char* base) {
- _items[_bcp_base] = base;
-}
-
-inline void ArgumentBootClassPath::add_prefix(const char* prefix) {
- _items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], prefix, true);
-}
-
-inline void ArgumentBootClassPath::add_suffix_to_prefix(const char* suffix) {
- _items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], suffix, false);
-}
-
-inline void ArgumentBootClassPath::add_suffix(const char* suffix) {
- _items[_bcp_suffix] = add_to_path(_items[_bcp_suffix], suffix, false);
-}
-
-inline void ArgumentBootClassPath::reset_item_at(int index) {
- assert(index < _bcp_nitems && index != _bcp_base, "just checking");
- if (_items[index] != NULL) {
- FREE_C_HEAP_ARRAY(char, _items[index]);
- _items[index] = NULL;
- }
-}
-
-inline void ArgumentBootClassPath::reset_path(const char* base) {
- // Clear the prefix and suffix.
- reset_item_at(_bcp_prefix);
- reset_item_at(_bcp_suffix);
- set_base(base);
-}
-
-//------------------------------------------------------------------------------
-
-
-// Combine the bootclasspath elements, some of which may be null, into a single
-// c-heap-allocated string.
-char* ArgumentBootClassPath::combined_path() {
- assert(_items[_bcp_base] != NULL, "empty default sysclasspath");
-
- size_t lengths[_bcp_nitems];
- size_t total_len = 0;
-
- const char separator = *os::path_separator();
-
- // Get the lengths.
- int i;
- for (i = 0; i < _bcp_nitems; ++i) {
- if (i == _bcp_suffix) {
- // Record index of boot loader's append path.
- Arguments::set_bootclassloader_append_index((int)total_len);
- }
- if (_items[i] != NULL) {
- lengths[i] = strlen(_items[i]);
- // Include space for the separator char (or a NULL for the last item).
- total_len += lengths[i] + 1;
- }
- }
- assert(total_len > 0, "empty sysclasspath not allowed");
-
- // Copy the _items to a single string.
- char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtArguments);
- char* cp_tmp = cp;
- for (i = 0; i < _bcp_nitems; ++i) {
- if (_items[i] != NULL) {
- memcpy(cp_tmp, _items[i], lengths[i]);
- cp_tmp += lengths[i];
- *cp_tmp++ = separator;
- }
- }
- *--cp_tmp = '\0'; // Replace the extra separator.
- return cp;
-}
-
-// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
-char*
-ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepend) {
- char *cp;
-
- assert(str != NULL, "just checking");
- if (path == NULL) {
- size_t len = strlen(str) + 1;
- cp = NEW_C_HEAP_ARRAY(char, len, mtArguments);
- memcpy(cp, str, len); // copy the trailing null
- } else {
- const char separator = *os::path_separator();
- size_t old_len = strlen(path);
- size_t str_len = strlen(str);
- size_t len = old_len + str_len + 2;
-
- if (prepend) {
- cp = NEW_C_HEAP_ARRAY(char, len, mtArguments);
- char* cp_tmp = cp;
- memcpy(cp_tmp, str, str_len);
- cp_tmp += str_len;
- *cp_tmp = separator;
- memcpy(++cp_tmp, path, old_len + 1); // copy the trailing null
- FREE_C_HEAP_ARRAY(char, path);
- } else {
- cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtArguments);
- char* cp_tmp = cp + old_len;
- *cp_tmp = separator;
- memcpy(++cp_tmp, str, str_len + 1); // copy the trailing null
- }
- }
- return cp;
-}
-
-// Scan the directory and append any jar or zip files found to path.
-// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
-char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) {
- DIR* dir = os::opendir(directory);
- if (dir == NULL) return path;
-
- char dir_sep[2] = { '\0', '\0' };
- size_t directory_len = strlen(directory);
- const char fileSep = *os::file_separator();
- if (directory[directory_len - 1] != fileSep) dir_sep[0] = fileSep;
-
- /* Scan the directory for jars/zips, appending them to path. */
- struct dirent *entry;
- char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments);
- while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
- const char* name = entry->d_name;
- const char* ext = name + strlen(name) - 4;
- bool isJarOrZip = ext > name &&
- (os::file_name_strcmp(ext, ".jar") == 0 ||
- os::file_name_strcmp(ext, ".zip") == 0);
- if (isJarOrZip) {
- char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtArguments);
- sprintf(jarpath, "%s%s%s", directory, dir_sep, name);
- path = add_to_path(path, jarpath, false);
- FREE_C_HEAP_ARRAY(char, jarpath);
- }
- }
- FREE_C_HEAP_ARRAY(char, dbuf);
- os::closedir(dir);
- return path;
-}
-
// Parses a size specification string.
bool Arguments::atojulong(const char *s, julong* result) {
julong n = 0;
@@ -2724,9 +2525,7 @@
jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
const JavaVMInitArgs *java_options_args,
const JavaVMInitArgs *cmd_line_args) {
- // For components of the system classpath.
- ArgumentBootClassPath bcp(Arguments::get_sysclasspath());
- bool bcp_assembly_required = false;
+ bool xpatch_javabase = false;
// Save default settings for some mode flags
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
@@ -2743,29 +2542,26 @@
// Parse args structure generated from JAVA_TOOL_OPTIONS environment
// variable (if present).
- jint result = parse_each_vm_init_arg(
- java_tool_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
+ jint result = parse_each_vm_init_arg(java_tool_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
if (result != JNI_OK) {
return result;
}
// Parse args structure generated from the command line flags.
- result = parse_each_vm_init_arg(cmd_line_args, &bcp, &bcp_assembly_required,
- Flag::COMMAND_LINE);
+ result = parse_each_vm_init_arg(cmd_line_args, &xpatch_javabase, Flag::COMMAND_LINE);
if (result != JNI_OK) {
return result;
}
// Parse args structure generated from the _JAVA_OPTIONS environment
// variable (if present) (mimics classic VM)
- result = parse_each_vm_init_arg(
- java_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
+ result = parse_each_vm_init_arg(java_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
if (result != JNI_OK) {
return result;
}
// Do final processing now that all arguments have been parsed
- result = finalize_vm_init_args(&bcp, bcp_assembly_required);
+ result = finalize_vm_init_args();
if (result != JNI_OK) {
return result;
}
@@ -2818,10 +2614,7 @@
return false;
}
-jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
- ArgumentBootClassPath* bcp_p,
- bool* bcp_assembly_required_p,
- Flag::Flags origin) {
+jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin) {
// For match_option to return remaining or value part of option string
const char* tail;
@@ -2877,8 +2670,8 @@
return JNI_EINVAL;
// -bootclasspath/a:
} else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
- bcp_p->add_suffix(tail);
- *bcp_assembly_required_p = true;
+ Arguments::set_bootclassloader_append_index((int)strlen(Arguments::get_sysclasspath())+1);
+ Arguments::append_sysclasspath(tail);
// -bootclasspath/p:
} else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
jio_fprintf(defaultStream::output_stream(),
@@ -2938,9 +2731,8 @@
if (tail != NULL) {
char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail);
add_init_agent("instrument", options, false);
- // java agents need module java.instrument. Also -addmods ALL-SYSTEM because
- // the java agent is in the unmamed module of the application class loader
- if (!Arguments::append_to_addmods_property("java.instrument,ALL-SYSTEM")) {
+ // java agents need module java.instrument
+ if (!Arguments::append_to_addmods_property("java.instrument")) {
return JNI_ENOMEM;
}
}
@@ -3218,37 +3010,30 @@
return JNI_ERR;
#endif
}
- if (match_option(option, "-Djdk.launcher.patch.0=", &tail)) {
- // -Xpatch
- int dir_count;
- char** patch_dirs = os::split_path(tail, &dir_count);
- if (patch_dirs == NULL) {
- jio_fprintf(defaultStream::output_stream(),
- "Bad value for -Xpatch.\n");
+ if (match_option(option, "-Djdk.launcher.patch.", &tail)) {
+ // -Djdk.launcher.patch.#=<module>=<file>(<pathsep><file>)*
+ // The number, #, specified will be increasing with each -Xpatch
+ // specified on the command line.
+ // Pick up module name, following the -D property's equal sign.
+ const char* property_equal = strchr(tail, '=');
+ if (property_equal == NULL) {
+ jio_fprintf(defaultStream::output_stream(), "Missing '=' in -Xpatch specification\n");
return JNI_ERR;
- }
- set_patch_dirs(patch_dirs);
- set_patch_dirs_count(dir_count);
-
- // Create a path for each patch dir consisting of dir/java.base.
- char file_sep = os::file_separator()[0];
- for (int x = 0; x < dir_count; x++) {
- // Really shouldn't be NULL, but check can't hurt
- if (patch_dirs[x] != NULL) {
- size_t len = strlen(patch_dirs[x]);
- if (len != 0) { // Ignore empty strings.
- len += 11; // file_sep + "java.base" + null terminator.
- char* dir = NEW_C_HEAP_ARRAY(char, len, mtArguments);
- jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep);
-
- // See if Xpatch module path exists.
- struct stat st;
- if ((os::stat(dir, &st) == 0)) {
- bcp_p->add_prefix(dir);
- *bcp_assembly_required_p = true;
- }
- FREE_C_HEAP_ARRAY(char, dir);
- }
+ } else {
+ // Find the equal sign between the module name and the path specification
+ const char* module_equal = strchr(property_equal + 1, '=');
+ if (module_equal == NULL) {
+ jio_fprintf(defaultStream::output_stream(), "Bad value for -Xpatch, no module name specified\n");
+ return JNI_ERR;
+ } else {
+ // Pick out the module name, in between the two equal signs
+ size_t module_len = module_equal - property_equal - 1;
+ char* module_name = NEW_C_HEAP_ARRAY(char, module_len+1, mtArguments);
+ memcpy(module_name, property_equal + 1, module_len);
+ *(module_name + module_len) = '\0';
+ // The path piece begins one past the module_equal sign
+ Arguments::add_xpatchprefix(module_name, module_equal + 1, xpatch_javabase);
+ FREE_C_HEAP_ARRAY(char, module_name);
}
}
}
@@ -3511,6 +3296,27 @@
return JNI_OK;
}
+void Arguments::add_xpatchprefix(const char* module_name, const char* path, bool* xpatch_javabase) {
+ // For java.base check for duplicate -Xpatch options being specified on the command line.
+ // This check is only required for java.base, all other duplicate module specifications
+ // will be checked during module system initialization. The module system initialization
+ // will throw an ExceptionInInitializerError if this situation occurs.
+ if (strcmp(module_name, "java.base") == 0) {
+ if (*xpatch_javabase) {
+ vm_exit_during_initialization("Cannot specify java.base more than once to -Xpatch");
+ } else {
+ *xpatch_javabase = true;
+ }
+ }
+
+ // Create GrowableArray lazily, only if -Xpatch has been specified
+ if (_xpatchprefix == NULL) {
+ _xpatchprefix = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<ModuleXPatchPath*>(10, true);
+ }
+
+ _xpatchprefix->push(new ModuleXPatchPath(module_name, path));
+}
+
// Set property jdk.boot.class.path.append to the contents of the bootclasspath
// that follows either the jimage file or exploded module directories. The
// property will contain -Xbootclasspath/a and/or jvmti appended additions.
@@ -3609,7 +3415,7 @@
return nonEmptyDirs;
}
-jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required) {
+jint Arguments::finalize_vm_init_args() {
// check if the default lib/endorsed directory exists; if so, error
char path[JVM_MAXPATHLEN];
const char* fileSep = os::file_separator();
@@ -3645,17 +3451,7 @@
return JNI_ERR;
}
- if (bcp_assembly_required) {
- // Assemble the bootclasspath elements into the final path.
- char *combined_path = bcp_p->combined_path();
- Arguments::set_sysclasspath(combined_path);
- FREE_C_HEAP_ARRAY(char, combined_path);
- } else {
- // At this point in sysclasspath processing anything
- // added would be considered in the boot loader's append path.
- // Record this index, including +1 for the file separator character.
- Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
- }
+ Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
// This must be done after all arguments have been processed.
// java_compiler() true means set to "NONE" or empty.
@@ -3704,6 +3500,12 @@
UNSUPPORTED_OPTION(TieredCompilation);
#endif
+#if INCLUDE_JVMCI
+ if (EnableJVMCI && !append_to_addmods_property("jdk.vm.ci")) {
+ return JNI_ENOMEM;
+ }
+#endif
+
// If we are running in a headless jre, force java.awt.headless property
// to be true unless the property has already been set.
// Also allow the OS environment variable JAVA_AWT_HEADLESS to set headless state.
@@ -4005,7 +3807,7 @@
void Arguments::set_shared_spaces_flags() {
if (DumpSharedSpaces) {
- if (Arguments::patch_dirs() != NULL) {
+ if (Arguments::get_xpatchprefix() != NULL) {
vm_exit_during_initialization(
"Cannot use the following option when dumping the shared archive", "-Xpatch");
}
--- a/hotspot/src/share/vm/runtime/arguments.hpp Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Fri May 06 06:23:29 2016 -0700
@@ -41,17 +41,15 @@
typedef jint (JNICALL *vfprintf_hook_t)(FILE *fp, const char *format, va_list args) ATTRIBUTE_PRINTF(2, 0);
}
-// Forward declarations
-class ArgumentBootClassPath;
-
-// PathString is used as the underlying value container for a
-// SystemProperty and for the string that represents the system
-// boot class path, Arguments::_system_boot_class_path.
+// PathString is used as:
+// - the underlying value for a SystemProperty
+// - the path portion of an -Xpatch module/path pair
+// - the string that represents the system boot class path, Arguments::_system_boot_class_path.
class PathString : public CHeapObj<mtArguments> {
protected:
- char* _value;
+ char* _value;
public:
- char* value() const { return _value; }
+ char* value() const { return _value; }
bool set_value(const char *value) {
if (_value != NULL) {
@@ -92,7 +90,6 @@
}
}
- // Constructor
PathString(const char* value) {
if (value == NULL) {
_value = NULL;
@@ -101,6 +98,43 @@
strcpy(_value, value);
}
}
+
+ ~PathString() {
+ if (_value != NULL) {
+ FreeHeap(_value);
+ _value = NULL;
+ }
+ }
+};
+
+// ModuleXPatchPath records the module/path pair as specified to -Xpatch.
+class ModuleXPatchPath : public CHeapObj<mtInternal> {
+private:
+ char* _module_name;
+ PathString* _path;
+public:
+ ModuleXPatchPath(const char* module_name, const char* path) {
+ assert(module_name != NULL && path != NULL, "Invalid module name or path value");
+ size_t len = strlen(module_name) + 1;
+ _module_name = AllocateHeap(len, mtInternal);
+ strncpy(_module_name, module_name, len); // copy the trailing null
+ _path = new PathString(path);
+ }
+
+ ~ModuleXPatchPath() {
+ if (_module_name != NULL) {
+ FreeHeap(_module_name);
+ _module_name = NULL;
+ }
+ if (_path != NULL) {
+ delete _path;
+ _path = NULL;
+ }
+ }
+
+ inline void set_path(const char* path) { _path->set_value(path); }
+ inline const char* module_name() const { return _module_name; }
+ inline char* path_string() const { return _path->value(); }
};
// Element describing System and User (-Dkey=value flags) defined property.
@@ -114,7 +148,7 @@
SystemProperty* _next;
bool _internal;
bool _writeable;
- bool writeable() { return _writeable; }
+ bool writeable() { return _writeable; }
public:
// Accessors
@@ -314,10 +348,19 @@
static SystemProperty *_java_class_path;
static SystemProperty *_jdk_boot_class_path_append;
+ // -Xpatch:module=<file>(<pathsep><file>)*
+ // Each element contains the associated module name, path
+ // string pair as specified to -Xpatch.
+ static GrowableArray<ModuleXPatchPath*>* _xpatchprefix;
+
// The constructed value of the system class path after
// argument processing and JVMTI OnLoad additions via
// calls to AddToBootstrapClassLoaderSearch. This is the
// final form before ClassLoader::setup_bootstrap_search().
+ // Note: since -Xpatch is a module name/path pair, the system
+ // boot class path string no longer contains the "prefix" to
+ // the boot class path base piece as it did when
+ // -Xbootclasspath/p was supported.
static PathString *_system_boot_class_path;
// temporary: to emit warning if the default ext dirs are not empty.
@@ -373,12 +416,6 @@
// mark the boot loader's append path observability boundary.
static int _bootclassloader_append_index;
- // -Xpatch flag
- static char** _patch_dirs;
- static int _patch_dirs_count;
- static void set_patch_dirs(char** dirs) { _patch_dirs = dirs; }
- static void set_patch_dirs_count(int count) { _patch_dirs_count = count; }
-
// -Xdebug flag
static bool _xdebug_mode;
static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; }
@@ -465,8 +502,8 @@
static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
const JavaVMInitArgs *java_options_args,
const JavaVMInitArgs *cmd_line_args);
- static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, ArgumentBootClassPath* bcp_p, bool* bcp_assembly_required_p, Flag::Flags origin);
- static jint finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required);
+ static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin);
+ static jint finalize_vm_init_args();
static bool is_bad_option(const JavaVMOption* option, jboolean ignore, const char* option_type);
static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
@@ -637,13 +674,12 @@
return _bootclassloader_append_index;
}
static void set_bootclassloader_append_index(int value) {
- _bootclassloader_append_index = value;
+ // Set only if the index has not been set yet
+ if (_bootclassloader_append_index == -1) {
+ _bootclassloader_append_index = value;
+ }
}
- // -Xpatch
- static char** patch_dirs() { return _patch_dirs; }
- static int patch_dirs_count() { return _patch_dirs_count; }
-
// -Xrun
static AgentLibrary* libraries() { return _libraryList.first(); }
static bool init_libraries_at_startup() { return !_libraryList.is_empty(); }
@@ -701,8 +737,8 @@
static void set_library_path(const char *value) { _java_library_path->set_value(value); }
static void set_ext_dirs(char *value) { _ext_dirs = os::strdup_check_oom(value); }
- // Set up of the underlying system boot class path
- static void set_jdkbootclasspath_append();
+ // Set up the underlying pieces of the system boot class path
+ static void add_xpatchprefix(const char *module_name, const char *path, bool* xpatch_javabase);
static void set_sysclasspath(const char *value) {
_system_boot_class_path->set_value(value);
set_jdkbootclasspath_append();
@@ -711,11 +747,15 @@
_system_boot_class_path->append_value(value);
set_jdkbootclasspath_append();
}
+ static void set_jdkbootclasspath_append();
- static char* get_java_home() { return _java_home->value(); }
- static char* get_dll_dir() { return _sun_boot_library_path->value(); }
+ static GrowableArray<ModuleXPatchPath*>* get_xpatchprefix() { return _xpatchprefix; }
static char* get_sysclasspath() { return _system_boot_class_path->value(); }
- static char* get_ext_dirs() { return _ext_dirs; }
+ static char* get_jdk_boot_class_path_append() { return _jdk_boot_class_path_append->value(); }
+
+ static char* get_java_home() { return _java_home->value(); }
+ static char* get_dll_dir() { return _sun_boot_library_path->value(); }
+ static char* get_ext_dirs() { return _ext_dirs; }
static char* get_appclasspath() { return _java_class_path->value(); }
static void fix_appclasspath();
--- a/hotspot/src/share/vm/runtime/init.cpp Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/src/share/vm/runtime/init.cpp Fri May 06 06:23:29 2016 -0700
@@ -52,7 +52,8 @@
// Initialization done by Java thread in init_globals()
void management_init();
void bytecodes_init();
-void classLoader_init();
+void classLoader_init1();
+void classLoader_init2(); // note: ClassLoader need 2-phase init
void compilationPolicy_init();
void codeCache_init();
void VM_Version_init();
@@ -102,7 +103,7 @@
HandleMark hm;
management_init();
bytecodes_init();
- classLoader_init();
+ classLoader_init1();
compilationPolicy_init();
codeCache_init();
CodeCacheExtensions::initialize();
@@ -116,6 +117,7 @@
if (status != JNI_OK)
return status;
+ classLoader_init2(); // after SymbolTable creation, set up -Xpatch entries
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Universe);
interpreter_init(); // before any methods loaded
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Interpreter);
--- a/hotspot/test/TEST.ROOT Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/TEST.ROOT Fri May 06 06:23:29 2016 -0700
@@ -36,9 +36,12 @@
requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java
requires.properties=sun.arch.data.model
-# Tests using jtreg 4.2 b01 features
-requiredVersion=4.2 b01
+# Tests using jtreg 4.2 b02 features
+requiredVersion=4.2 b02
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
external.lib.roots = ../../
+
+# Use new form of -Xpatch
+useNewXpatch=true
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestI.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestI.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestL.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestL.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableBoolean.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableBoolean.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableByte.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableByte.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableChar.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableChar.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableDouble.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableDouble.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableFloat.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableFloat.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableInt.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableInt.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableLong.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableLong.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableMemoryBarrier.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableMemoryBarrier.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
--- a/hotspot/test/compiler/stable/TestStableObject.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableObject.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/stable/TestStableShort.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/stable/TestStableShort.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Fri May 06 06:23:29 2016 -0700
@@ -40,6 +40,7 @@
* -XX:CompileCommand=dontinline,UnsafeGetConstantField.checkGetAddress()
* -XX:CompileCommand=dontinline,*.test*
* -XX:+UseUnalignedAccesses
+ * -XaddReads:java.base=ALL-UNNAMED
* compiler.unsafe.UnsafeGetConstantField
*
* @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions
@@ -49,6 +50,7 @@
* -XX:CompileCommand=dontinline,*.test*
* -XX:CompileCommand=inline,*Unsafe.get*
* -XX:-UseUnalignedAccesses
+ * -XaddReads:java.base=ALL-UNNAMED
* compiler.unsafe.UnsafeGetConstantField
*/
package compiler.unsafe;
--- a/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -48,7 +48,7 @@
"-Xmodule:java.base"),
"mods/java.base");
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods", "-version");
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.base=mods/java.base", "-version");
new OutputAnalyzer(pb.start())
.shouldContain("Incompatible definition of java.lang.Object")
.shouldHaveExitValue(1);
--- a/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java Fri May 06 06:23:29 2016 -0700
@@ -120,9 +120,9 @@
getPkg("java/nio/charset", "jrt:/java.base");
// Test a package in a module not owned by boot loader.
- Class clss = Class.forName("javax.activation.DataHandler");
+ Class clss = Class.forName("jdk.nio.zipfs.ZipPath");
if (clss == null)
- throw new RuntimeException("Could not find class javax.activation.DataHandler");
+ throw new RuntimeException("Could not find class jdk.nio.zipfs.ZipPath");
getPkg("javax/activation", null); // Not owned by boot loader
// Test a package not in jimage file.
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java Fri May 06 06:23:29 2016 -0700
@@ -210,9 +210,9 @@
// now use the same loader to load class p1.c1Loose
Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1Loose");
- // change m1 to be a loose module
+ // change m1 to read all unnamed modules
Module m1 = layer.findModule("m1").get();
- jdk.internal.module.Modules.addReads(m1, null);
+ jdk.internal.module.Modules.addReadsAllUnnamed(m1);
try {
p1_c1_class.newInstance();
--- a/hotspot/test/runtime/modules/AccessCheck/Umod.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod.java Fri May 06 06:23:29 2016 -0700
@@ -201,9 +201,9 @@
// now use the same loader to load class p1.c1Loose
Class p1_c1_class = loader.loadClass("p1.c1Loose");
- // change m1 to be a loose module
+ // change m1 to read all unnamed modules
Module m1 = layer.findModule("m1").get();
- jdk.internal.module.Modules.addReads(m1, null);
+ jdk.internal.module.Modules.addReadsAllUnnamed(m1);
try {
p1_c1_class.newInstance();
--- a/hotspot/test/runtime/modules/JVMAddReadsModule.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/JVMAddReadsModule.java Fri May 06 06:23:29 2016 -0700
@@ -49,26 +49,27 @@
assertNotNull(to_module, "Module should not be null");
ModuleHelper.DefineModule(to_module, "9.0", "to_module/here", new String[] { "yourpackage" });
- // Null from_module argument, expect an NPE
+ // Null from_module argument, expect NPE
try {
ModuleHelper.AddReadsModule(null, to_module);
throw new RuntimeException("Failed to get the expected NPE");
- } catch(NullPointerException e) {
+ } catch (NullPointerException e) {
// Expected
}
- // Null to_module argument, do not expect an NPE
+ // Null to_module argument, expect NPE
try {
ModuleHelper.AddReadsModule(from_module, null);
- } catch(NullPointerException e) {
throw new RuntimeException("Unexpected NPE was thrown");
+ } catch (NullPointerException e) {
+ // Expected
}
- // Null from_module and to_module arguments, expect an NPE
+ // Null from_module and to_module arguments, expect NPE
try {
ModuleHelper.AddReadsModule(null, null);
throw new RuntimeException("Failed to get the expected NPE");
- } catch(NullPointerException e) {
+ } catch (NullPointerException e) {
// Expected
}
--- a/hotspot/test/runtime/modules/Visibility/XpatchVisibility.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/Visibility/XpatchVisibility.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -83,7 +83,7 @@
"p2" + File.separator + "Vis2_B.class"));
new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(
- "-Xpatch:mods2",
+ "-Xpatch:java.base=mods2/java.base",
"-XaddExports:java.base/p2=ALL-UNNAMED",
"Vis2_A")
.start()).shouldHaveExitValue(0);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/BasicJarBuilder.java Fri May 06 06:23:29 2016 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @summary Simple jar builder
+ * Input: jarName className1 className2 ...
+ * do not specify extensions, just the names
+ * E.g. prot_domain ProtDomainA ProtDomainB
+ * Output: A jar containing compiled classes, placed in a test classes folder
+ */
+
+import jdk.test.lib.*;
+
+import java.io.File;
+import java.util.ArrayList;
+import sun.tools.jar.Main;
+
+// Using JarBuilder requires that all to-be-jarred classes should be placed
+// in the current working directory, aka "."
+public class BasicJarBuilder {
+ private static final String classDir = System.getProperty("test.classes");
+
+ public static void build(boolean classesInWorkDir, String jarName,
+ String ...classNames) throws Exception {
+
+ if (classesInWorkDir) {
+ createSimpleJar(".", classDir + File.separator + jarName + ".jar", classNames);
+ } else {
+ build(jarName, classNames);
+ }
+ }
+
+ public static void build(String jarName, String ...classNames) throws Exception {
+ createSimpleJar(classDir, classDir + File.separator + jarName + ".jar",
+ classNames);
+ }
+
+ private static void createSimpleJar(String jarclassDir, String jarName,
+ String[] classNames) throws Exception {
+ ArrayList<String> args = new ArrayList<String>();
+ args.add("cf");
+ args.add(jarName);
+ addClassArgs(args, jarclassDir, classNames);
+ createJar(args);
+ }
+
+ private static void addClassArgs(ArrayList<String> args, String jarclassDir,
+ String[] classNames) {
+
+ for (String name : classNames) {
+ args.add("-C");
+ args.add(jarclassDir);
+ args.add(name + ".class");
+ }
+ }
+
+ private static void createJar(ArrayList<String> args) {
+ Main jarTool = new Main(System.out, System.err, "jar");
+ if (!jarTool.run(args.toArray(new String[1]))) {
+ throw new RuntimeException("jar operation failed");
+ }
+ }
+
+ // Get full path to the test jar
+ public static String getTestJar(String jar) {
+ File dir = new File(System.getProperty("test.classes", "."));
+ File jarFile = new File(dir, jar);
+ if (!jarFile.exists()) {
+ throw new RuntimeException("Cannot find " + jarFile.getPath());
+ }
+ if (!jarFile.isFile()) {
+ throw new RuntimeException("Not a regular file: " + jarFile.getPath());
+ }
+ return jarFile.getPath();
+ }
+}
--- a/hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -58,7 +58,8 @@
"mods2/java.desktop");
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
- "-Xpatch:mods" + File.pathSeparator + "mods2",
+ "-Xpatch:java.naming=mods/java.naming",
+ "-Xpatch:java.desktop=mods2/java.desktop",
"Xpatch2DirsMain", "javax.naming.spi.NamingManager", "java.beans.Encoder");
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchDupJavaBase.java Fri May 06 06:23:29 2016 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary VM exit initialization results if java.base is specificed more than once to Xpatch.
+ * @library /testlibrary
+ */
+
+import jdk.test.lib.*;
+
+public class XpatchDupJavaBase {
+ // The VM should exit initialization if java.base is specified
+ // more than once to -Xpatch.
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-Xpatch:java.base=javabase_dir",
+ "-Xpatch:java.base=javabase_dir",
+ "-version");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Cannot specify java.base more than once to -Xpatch");
+ output.shouldHaveExitValue(1);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchDupModule.java Fri May 06 06:23:29 2016 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Module system initialization exception results if a module is specificed twice to Xpatch.
+ * @library /testlibrary
+ */
+
+import jdk.test.lib.*;
+
+public class XpatchDupModule {
+
+ // The module system initialization should generate an ExceptionInInitializerError
+ // if -Xpatch is specified with the same module more than once.
+
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-Xpatch:module1=module1_dir",
+ "-Xpatch:module1=module1_dir",
+ "-version");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("java.lang.ExceptionInInitializerError");
+ output.shouldHaveExitValue(1);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchJavaBase.java Fri May 06 06:23:29 2016 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8130399
+ * @summary Make sure -Xpatch works for java.base.
+ * @library /testlibrary
+ * @compile XpatchMain.java
+ * @run main XpatchJavaBase
+ */
+
+import jdk.test.lib.*;
+
+public class XpatchJavaBase {
+
+ public static void main(String[] args) throws Exception {
+ String source = "package java.lang; " +
+ "public class NewClass { " +
+ " static { " +
+ " System.out.println(\"I pass!\"); " +
+ " } " +
+ "}";
+
+ ClassFileInstaller.writeClassToDisk("java/lang/NewClass",
+ InMemoryJavaCompiler.compile("java.lang.NewClass", source, "-Xmodule:java.base"),
+ "mods/java.base");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.base=mods/java.base",
+ "XpatchMain", "java.lang.NewClass");
+
+ new OutputAnalyzer(pb.start())
+ .shouldContain("I pass!")
+ .shouldHaveExitValue(0);
+ }
+}
--- a/hotspot/test/runtime/modules/Xpatch/XpatchTest.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchTest.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -47,7 +47,7 @@
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
"mods/java.naming");
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods",
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming",
"XpatchMain", "javax.naming.spi.NamingManager");
new OutputAnalyzer(pb.start())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchTestJar.java Fri May 06 06:23:29 2016 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Make sure -Xpatch works when a jar file is specified for a module
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * jdk.jartool/sun.tools.jar
+ * @build BasicJarBuilder
+ * @compile XpatchMain.java
+ * @run main XpatchTestJar
+ */
+
+import jdk.test.lib.*;
+
+public class XpatchTestJar {
+ private static String moduleJar;
+
+ public static void main(String[] args) throws Exception {
+
+ // Create a class file in the module java.naming. This class file
+ // will be put in the javanaming.jar file.
+ String source = "package javax.naming.spi; " +
+ "public class NamingManager { " +
+ " static { " +
+ " System.out.println(\"I pass!\"); " +
+ " } " +
+ "}";
+
+ ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
+ InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+ System.getProperty("test.classes"));
+
+ // Build the jar file that will be used for the module "java.naming".
+ BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
+ moduleJar = BasicJarBuilder.getTestJar("javanaming.jar");
+
+ // Just to make sure we are not fooled by the class file being on the
+ // class path where all the test classes are stored, write the NamingManager.class
+ // file out again with output that does not contain what OutputAnalyzer
+ // expects. This will provide confidence that the contents of the class
+ // is truly coming from the jar file and not the class file.
+ source = "package javax.naming.spi; " +
+ "public class NamingManager { " +
+ " static { " +
+ " System.out.println(\"Fail!\"); " +
+ " } " +
+ "}";
+
+ ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
+ InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+ System.getProperty("test.classes"));
+
+ // Supply -Xpatch with the name of the jar file for the module java.naming.
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=" + moduleJar,
+ "XpatchMain", "javax.naming.spi.NamingManager");
+
+ new OutputAnalyzer(pb.start())
+ .shouldContain("I pass!")
+ .shouldHaveExitValue(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchTestJarDir.java Fri May 06 06:23:29 2016 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Make sure -Xpatch works when a jar file and a directory is specified for a module
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * jdk.jartool/sun.tools.jar
+ * @build BasicJarBuilder
+ * @compile Xpatch2DirsMain.java
+ * @run main XpatchTestJarDir
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import jdk.test.lib.*;
+
+public class XpatchTestJarDir {
+ private static String moduleJar;
+
+ public static void main(String[] args) throws Exception {
+
+ // Create a class file in the module java.naming. This class file
+ // will be put in the javanaming.jar file.
+ String source = "package javax.naming.spi; " +
+ "public class NamingManager1 { " +
+ " static { " +
+ " System.out.println(\"I pass one!\"); " +
+ " } " +
+ "}";
+
+ ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
+ InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
+ System.getProperty("test.classes"));
+
+ // Build the jar file that will be used for the module "java.naming".
+ BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager1");
+ moduleJar = BasicJarBuilder.getTestJar("javanaming.jar");
+
+ // Just to make sure we are not fooled by the class file being on the
+ // class path where all the test classes are stored, write the NamingManager.class
+ // file out again with output that does not contain what OutputAnalyzer
+ // expects. This will provide confidence that the contents of the class
+ // is truly coming from the jar file and not the class file.
+ source = "package javax.naming.spi; " +
+ "public class NamingManager1 { " +
+ " static { " +
+ " System.out.println(\"Fail!\"); " +
+ " } " +
+ "}";
+
+ ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
+ InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
+ System.getProperty("test.classes"));
+
+ // Create a second class file in the module java.naming. This class file
+ // will be put in the mods/java.naming directory.
+ source = "package javax.naming.spi; " +
+ "public class NamingManager2 { " +
+ " static { " +
+ " System.out.println(\"I pass two!\"); " +
+ " } " +
+ "}";
+
+ ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager2",
+ InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager2", source, "-Xmodule:java.naming"),
+ (System.getProperty("test.classes") + "/mods/java.naming"));
+
+
+ // Supply -Xpatch with the name of the jar file for the module java.naming.
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=" +
+ moduleJar +
+ File.pathSeparator +
+ System.getProperty("test.classes") + "/mods/java.naming",
+ "Xpatch2DirsMain",
+ "javax.naming.spi.NamingManager1",
+ "javax.naming.spi.NamingManager2");
+
+ new OutputAnalyzer(pb.start())
+ .shouldContain("I pass one!")
+ .shouldContain("I pass two!")
+ .shouldHaveExitValue(0);
+ }
+}
--- a/hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java Fri May 06 06:23:29 2016 -0700
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8069469
- * @summary Make sure -XX:+TraceClassLoading works properly with "modules" jimage,
+ * @summary Make sure -Xlog:classload=info works properly with "modules" jimage,
-Xpatch, and with -Xbootclasspath/a
* @modules java.base/jdk.internal.misc
* @library /testlibrary
@@ -45,24 +45,23 @@
" } " +
"}";
- // Test -XX:+TraceClassLoading output for -Xpatch
+ // Test -Xlog:classload=info output for -Xpatch
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
"mods/java.naming");
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods",
- "-XX:+TraceClassLoading", "XpatchMain", "javax.naming.spi.NamingManager");
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming",
+ "-Xlog:class+load=info", "XpatchMain", "javax.naming.spi.NamingManager");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
// "modules" jimage case.
output.shouldContain("[class,load] java.lang.Thread source: jrt:/java.base");
// -Xpatch case.
- output.shouldContain("[class,load] javax.naming.spi.NamingManager source: mods" +
- File.separator + "java.naming");
+ output.shouldContain("[class,load] javax.naming.spi.NamingManager source: mods/java.naming");
// -cp case.
output.shouldContain("[class,load] XpatchMain source: file");
- // Test -XX:+TraceClassLoading output for -Xbootclasspath/a
+ // Test -Xlog:classload=info output for -Xbootclasspath/a
source = "package XpatchTraceCL_pkg; " +
"public class ItIsI { " +
" static { " +
@@ -75,7 +74,7 @@
"xbcp");
pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:xbcp",
- "-XX:+TraceClassLoading", "XpatchMain", "XpatchTraceCL_pkg.ItIsI");
+ "-Xlog:class+load=info", "XpatchMain", "XpatchTraceCL_pkg.ItIsI");
output = new OutputAnalyzer(pb.start());
// -Xbootclasspath/a case.
output.shouldContain("[class,load] XpatchTraceCL_pkg.ItIsI source: xbcp");
--- a/hotspot/test/runtime/modules/XpatchCDS.java Fri May 06 09:54:58 2016 +0000
+++ b/hotspot/test/runtime/modules/XpatchCDS.java Fri May 06 06:23:29 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -35,7 +35,7 @@
public static void main(String args[]) throws Throwable {
System.out.println("Test that -Xpatch and -Xshare:dump are incompatibable");
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:.", "-Xshare:dump");
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming", "-Xshare:dump");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Cannot use the following option when dumping the shared archive: -Xpatch");
@@ -52,7 +52,7 @@
"-XX:+UnlockDiagnosticVMOptions",
"-XX:SharedArchiveFile=" + filename,
"-Xshare:on",
- "-Xpatch:.",
+ "-Xpatch:java.naming=mods/java.naming",
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("The shared archive file cannot be used with -Xpatch");