8194812: Extend class-data sharing to support the module path
8199360: Rework the support for the 'ignored' module options in CDS
Reviewed-by: jiangli, lfoltan, iklam, mseledtsov
--- a/src/hotspot/share/classfile/classLoader.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/classLoader.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -148,6 +148,8 @@
#if INCLUDE_CDS
ClassPathEntry* ClassLoader::_app_classpath_entries = NULL;
ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL;
+ClassPathEntry* ClassLoader::_module_path_entries = NULL;
+ClassPathEntry* ClassLoader::_last_module_path_entry = NULL;
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
#endif
@@ -721,7 +723,44 @@
}
}
-#endif
+void ClassLoader::add_to_module_path_entries(const char* path,
+ ClassPathEntry* entry) {
+ assert(entry != NULL, "ClassPathEntry should not be NULL");
+ assert(DumpSharedSpaces, "dump time only");
+
+ // The entry does not exist, add to the list
+ if (_module_path_entries == NULL) {
+ assert(_last_module_path_entry == NULL, "Sanity");
+ _module_path_entries = _last_module_path_entry = entry;
+ } else {
+ _last_module_path_entry->set_next(entry);
+ _last_module_path_entry = entry;
+ }
+}
+
+// Add a module path to the _module_path_entries list.
+void ClassLoader::update_module_path_entry_list(const char *path, TRAPS) {
+ assert(DumpSharedSpaces, "dump time only");
+ struct stat st;
+ int ret = os::stat(path, &st);
+ assert(ret == 0, "module path must exist");
+ // File or directory found
+ ClassPathEntry* new_entry = NULL;
+ new_entry = create_class_path_entry(path, &st, true /* throw_exception */,
+ false /*is_boot_append */, CHECK);
+ if (new_entry == NULL) {
+ return;
+ }
+
+ add_to_module_path_entries(path, new_entry);
+ return;
+}
+
+void ClassLoader::setup_module_search_path(const char* path, TRAPS) {
+ check_shared_classpath(path);
+ update_module_path_entry_list(path, THREAD);
+}
+#endif // INCLUDE_CDS
// Construct the array of module/path pairs as specified to --patch-module
// for the boot loader to search ahead of the jimage, if the class being
@@ -1512,7 +1551,7 @@
}
#if INCLUDE_CDS
-static char* skip_uri_protocol(char* source) {
+char* ClassLoader::skip_uri_protocol(char* source) {
if (strncmp(source, "file:", 5) == 0) {
// file: protocol path could start with file:/ or file:///
// locate the char after all the forward slashes
@@ -1533,7 +1572,7 @@
// Record the shared classpath index and loader type for classes loaded
// by the builtin loaders at dump time.
-void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream) {
+void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS) {
assert(DumpSharedSpaces, "sanity");
assert(stream != NULL, "sanity");
@@ -1542,9 +1581,10 @@
return;
}
+ oop loader = ik->class_loader();
char* src = (char*)stream->source();
if (src == NULL) {
- if (ik->class_loader() == NULL) {
+ if (loader == NULL) {
// JFR classes
ik->set_shared_classpath_index(0);
ik->set_class_loader_type(ClassLoader::BOOT_LOADER);
@@ -1554,41 +1594,84 @@
assert(has_jrt_entry(), "CDS dumping does not support exploded JDK build");
- ModuleEntry* module = ik->module();
+ ResourceMark rm(THREAD);
int classpath_index = -1;
- ResourceMark rm;
- char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
+ PackageEntry* pkg_entry = ik->package();
+
+ if (FileMapInfo::get_number_of_shared_paths() > 0) {
+ char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
- // save the path from the file: protocol or the module name from the jrt: protocol
- // if no protocol prefix is found, path is the same as stream->source()
- char* path = skip_uri_protocol(src);
- for (int i = 0; i < FileMapInfo::get_number_of_share_classpaths(); i++) {
- SharedClassPathEntry* ent = FileMapInfo::shared_classpath(i);
- if (get_canonical_path(ent->name(), canonical_path, JVM_MAXPATHLEN)) {
- // If the path (from the class stream srouce) is the same as the shared
- // class path, then we have a match. For classes from module image loaded by the
- // PlatformClassLoader, the stream->source() is not the name of the module image.
- // Need to look for 'jrt:' explicitly.
- if (strcmp(canonical_path, os::native_path((char*)path)) == 0 ||
- (i == 0 && string_starts_with(src, "jrt:"))) {
- classpath_index = i;
- break;
+ // save the path from the file: protocol or the module name from the jrt: protocol
+ // if no protocol prefix is found, path is the same as stream->source()
+ char* path = skip_uri_protocol(src);
+ for (int i = 0; i < FileMapInfo::get_number_of_shared_paths(); i++) {
+ SharedClassPathEntry* ent = FileMapInfo::shared_path(i);
+ if (get_canonical_path(ent->name(), canonical_path, JVM_MAXPATHLEN)) {
+ // If the path (from the class stream source) is the same as the shared
+ // class or module path, then we have a match.
+ if (strcmp(canonical_path, os::native_path((char*)path)) == 0) {
+ // NULL pkg_entry and pkg_entry in an unnamed module implies the class
+ // is from the -cp or boot loader append path which consists of -Xbootclasspath/a
+ // and jvmti appended entries.
+ if ((pkg_entry == NULL) || (pkg_entry->in_unnamed_module())) {
+ // Ensure the index is within the -cp range before assigning
+ // to the classpath_index.
+ if (SystemDictionary::is_system_class_loader(loader) &&
+ (i >= ClassLoaderExt::app_class_paths_start_index()) &&
+ (i < ClassLoaderExt::app_module_paths_start_index())) {
+ classpath_index = i;
+ break;
+ } else {
+ if ((i >= 1) &&
+ (i < ClassLoaderExt::app_class_paths_start_index())) {
+ // The class must be from boot loader append path which consists of
+ // -Xbootclasspath/a and jvmti appended entries.
+ assert(loader == NULL, "sanity");
+ classpath_index = i;
+ break;
+ }
+ }
+ } else {
+ // A class from a named module from the --module-path. Ensure the index is
+ // within the --module-path range before assigning to the classpath_index.
+ if ((pkg_entry != NULL) && !(pkg_entry->in_unnamed_module()) && (i > 0)) {
+ if (i >= ClassLoaderExt::app_module_paths_start_index() &&
+ i < FileMapInfo::get_number_of_shared_paths()) {
+ classpath_index = i;
+ break;
+ }
+ }
+ }
+ }
+ // for index 0 and the stream->source() is the modules image or has the jrt: protocol.
+ // The class must be from the runtime modules image.
+ if (i == 0 && (is_modules_image(src) || string_starts_with(src, "jrt:"))) {
+ classpath_index = i;
+ break;
+ }
}
}
- }
- if (classpath_index < 0) {
- // Shared classpath entry table only contains boot class path and -cp path.
+
// No path entry found for this class. Must be a shared class loaded by the
// user defined classloader.
- assert(ik->shared_classpath_index() < 0, "Sanity");
- return;
+ if (classpath_index < 0) {
+ assert(ik->shared_classpath_index() < 0, "Sanity");
+ return;
+ }
+ } else {
+ // The shared path table is set up after module system initialization.
+ // The path table contains no entry before that. Any classes loaded prior
+ // to the setup of the shared path table must be from the modules image.
+ assert(is_modules_image(src), "stream must be from modules image");
+ assert(FileMapInfo::get_number_of_shared_paths() == 0, "shared path table must not have been setup");
+ classpath_index = 0;
}
const char* const class_name = ik->name()->as_C_string();
const char* const file_name = file_name_for_class_name(class_name,
ik->name()->utf8_length());
assert(file_name != NULL, "invariant");
- Thread* THREAD = Thread::current();
+
ClassLoaderExt::Context context(class_name, file_name, CATCH);
context.record_result(ik->name(), classpath_index, ik, THREAD);
}
@@ -1673,6 +1756,13 @@
_shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
}
}
+
+void ClassLoader::initialize_module_path(TRAPS) {
+ if (DumpSharedSpaces) {
+ ClassLoaderExt::setup_module_paths(THREAD);
+ FileMapInfo::allocate_shared_path_table();
+ }
+}
#endif
jlong ClassLoader::classloader_time_ms() {
--- a/src/hotspot/share/classfile/classLoader.hpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/classLoader.hpp Tue Apr 10 11:43:40 2018 -0700
@@ -238,12 +238,18 @@
CDS_ONLY(static ClassPathEntry* _app_classpath_entries;)
CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;)
- CDS_ONLY(static void setup_app_search_path(const char *class_path);)
+ CDS_ONLY(static ClassPathEntry* _module_path_entries;)
+ CDS_ONLY(static ClassPathEntry* _last_module_path_entry;)
+ CDS_ONLY(static void setup_app_search_path(const char* class_path);)
+ CDS_ONLY(static void setup_module_search_path(const char* path, TRAPS);)
static void add_to_app_classpath_entries(const char* path,
ClassPathEntry* entry,
bool check_for_duplicates);
+ CDS_ONLY(static void add_to_module_path_entries(const char* path,
+ ClassPathEntry* entry);)
public:
CDS_ONLY(static ClassPathEntry* app_classpath_entries() {return _app_classpath_entries;})
+ CDS_ONLY(static ClassPathEntry* module_path_entries() {return _module_path_entries;})
protected:
// Initialization:
@@ -286,6 +292,7 @@
bool check_for_duplicates,
bool is_boot_append,
bool throw_exception=true);
+ CDS_ONLY(static void update_module_path_entry_list(const char *path, TRAPS);)
static void print_bootclasspath();
// Timing
@@ -382,6 +389,7 @@
static void initialize();
static void classLoader_init2(TRAPS);
CDS_ONLY(static void initialize_shared_path();)
+ CDS_ONLY(static void initialize_module_path(TRAPS);)
static int compute_Object_vtable();
@@ -402,14 +410,28 @@
// entries during shared classpath setup time.
static int num_app_classpath_entries();
+ // Helper function used by CDS code to get the number of module path
+ // entries during shared classpath setup time.
+ static int num_module_path_entries() {
+ assert(DumpSharedSpaces, "Should only be called at CDS dump time");
+ int num_entries = 0;
+ ClassPathEntry* e= ClassLoader::_module_path_entries;
+ while (e != NULL) {
+ num_entries ++;
+ e = e->next();
+ }
+ return num_entries;
+ }
static void check_shared_classpath(const char *path);
static void finalize_shared_paths_misc_info();
static int get_shared_paths_misc_info_size();
static void* get_shared_paths_misc_info();
static bool check_shared_paths_misc_info(void* info, int size);
+ static int get_module_paths_misc_info_size();
+ static void* get_module_paths_misc_info();
static void exit_with_path_failure(const char* error, const char* message);
-
- static void record_result(InstanceKlass* ik, const ClassFileStream* stream);
+ static char* skip_uri_protocol(char* source);
+ static void record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS);
#endif
static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name,
const char* file_name, jlong &size);
--- a/src/hotspot/share/classfile/classLoaderExt.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -30,6 +30,7 @@
#include "classfile/classLoaderExt.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/klassFactory.hpp"
+#include "classfile/modules.hpp"
#include "classfile/sharedClassUtil.hpp"
#include "classfile/sharedPathsMiscInfo.hpp"
#include "classfile/systemDictionaryShared.hpp"
@@ -41,19 +42,21 @@
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/arguments.hpp"
+#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.hpp"
#include "services/threadService.hpp"
#include "utilities/stringUtils.hpp"
-jshort ClassLoaderExt::_app_paths_start_index = ClassLoaderExt::max_classpath_index;
+jshort ClassLoaderExt::_app_class_paths_start_index = ClassLoaderExt::max_classpath_index;
+jshort ClassLoaderExt::_app_module_paths_start_index = ClassLoaderExt::max_classpath_index;
bool ClassLoaderExt::_has_app_classes = false;
bool ClassLoaderExt::_has_platform_classes = false;
void ClassLoaderExt::setup_app_search_path() {
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
- _app_paths_start_index = ClassLoader::num_boot_classpath_entries();
+ _app_class_paths_start_index = ClassLoader::num_boot_classpath_entries();
char* app_class_path = os::strdup(Arguments::get_appclasspath());
if (strcmp(app_class_path, ".") == 0) {
@@ -68,6 +71,29 @@
}
}
+void ClassLoaderExt::process_module_table(ModuleEntryTable* met, TRAPS) {
+ ResourceMark rm;
+ for (int i = 0; i < met->table_size(); i++) {
+ for (ModuleEntry* m = met->bucket(i); m != NULL;) {
+ char* path = m->location()->as_C_string();
+ if (strncmp(path, "file:", 5) == 0 && ClassLoader::string_ends_with(path, ".jar")) {
+ m->print();
+ path = ClassLoader::skip_uri_protocol(path);
+ ClassLoader::setup_module_search_path(path, THREAD);
+ }
+ m = m->next();
+ }
+ }
+}
+void ClassLoaderExt::setup_module_search_path(TRAPS) {
+ assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
+ _app_module_paths_start_index = ClassLoader::num_boot_classpath_entries() +
+ ClassLoader::num_app_classpath_entries();
+ Handle system_class_loader (THREAD, SystemDictionary::java_system_loader());
+ ModuleEntryTable* met = Modules::get_module_entry_table(system_class_loader);
+ process_module_table(met, THREAD);
+}
+
char* ClassLoaderExt::read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS) {
const char* name = "META-INF/MANIFEST.MF";
char* manifest;
@@ -195,6 +221,12 @@
}
}
+void ClassLoaderExt::setup_module_paths(TRAPS) {
+ if (UseAppCDS) {
+ ClassLoaderExt::setup_module_search_path(THREAD);
+ }
+}
+
Thread* ClassLoaderExt::Context::_dump_thread = NULL;
void ClassLoaderExt::record_result(ClassLoaderExt::Context *context,
--- a/src/hotspot/share/classfile/classLoaderExt.hpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/classLoaderExt.hpp Tue Apr 10 11:43:40 2018 -0700
@@ -26,6 +26,7 @@
#define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
#include "classfile/classLoader.hpp"
+#include "classfile/moduleEntry.hpp"
#include "utilities/macros.hpp"
CDS_ONLY(class SharedPathsMiscInfoExt;)
@@ -59,14 +60,14 @@
_file_name = file_name;
#if INCLUDE_CDS
if (!DumpSharedSpaces && !UseSharedSpaces) {
- // Must not modify _app_paths_start_index if we're not using CDS.
- assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
+ // Must not modify _app_class_paths_start_index if we're not using CDS.
+ assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
}
#endif
}
bool should_verify(int classpath_index) {
- CDS_ONLY(return (classpath_index >= _app_paths_start_index);)
+ CDS_ONLY(return (classpath_index >= _app_class_paths_start_index);)
NOT_CDS(return false;)
}
@@ -82,8 +83,8 @@
~Context() {
#if INCLUDE_CDS
if (!DumpSharedSpaces && !UseSharedSpaces) {
- // Must not modify app_paths_start_index if we're not using CDS.
- assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
+ // Must not modify app_class_paths_start_index if we're not using CDS.
+ assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
}
#endif
}
@@ -93,10 +94,16 @@
#if INCLUDE_CDS
static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size);
static void setup_app_search_path(); // Only when -Xshare:dump
+ static void process_module_table(ModuleEntryTable* met, TRAPS);
+ static void setup_module_search_path(TRAPS);
static SharedPathsMiscInfoExt* shared_paths_misc_info() {
return (SharedPathsMiscInfoExt*)_shared_paths_misc_info;
}
- static jshort _app_paths_start_index; // index of first app JAR in shared classpath entry table
+ // index of first app JAR in shared classpath entry table
+ static jshort _app_class_paths_start_index;
+ // index of first modular JAR in shared modulepath entry table
+ static jshort _app_module_paths_start_index;
+
static bool _has_app_classes;
static bool _has_platform_classes;
#endif
@@ -116,6 +123,7 @@
}
static void setup_search_paths() NOT_CDS_RETURN;
+ static void setup_module_paths(TRAPS) NOT_CDS_RETURN;
#if INCLUDE_CDS
private:
@@ -137,14 +145,20 @@
static void finalize_shared_paths_misc_info();
- static jshort app_paths_start_index() { return _app_paths_start_index; }
+ static jshort app_class_paths_start_index() { return _app_class_paths_start_index; }
+
+ static jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
static void init_paths_start_index(jshort app_start) {
- _app_paths_start_index = app_start;
+ _app_class_paths_start_index = app_start;
+ }
+
+ static void init_app_module_paths_start_index(jshort module_start) {
+ _app_module_paths_start_index = module_start;
}
static bool is_boot_classpath(int classpath_index) {
- return classpath_index < _app_paths_start_index;
+ return classpath_index < _app_class_paths_start_index;
}
static bool has_platform_or_app_classes() {
--- a/src/hotspot/share/classfile/klassFactory.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/klassFactory.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -84,7 +84,7 @@
}
} else {
SharedClassPathEntry* ent =
- (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+ (SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
pathname = ent == NULL ? NULL : ent->name();
}
ClassFileStream* stream = new ClassFileStream(ptr,
@@ -232,7 +232,7 @@
#if INCLUDE_CDS
if (DumpSharedSpaces) {
- ClassLoader::record_result(result, stream);
+ ClassLoader::record_result(result, stream, THREAD);
#if INCLUDE_JVMTI
assert(cached_class_file == NULL, "Sanity");
// Archive the class stream data into the optional data section
--- a/src/hotspot/share/classfile/modules.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/modules.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -85,7 +85,7 @@
return java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(version));
}
-static ModuleEntryTable* get_module_entry_table(Handle h_loader) {
+ModuleEntryTable* Modules::get_module_entry_table(Handle h_loader) {
// This code can be called during start-up, before the classLoader's classLoader data got
// created. So, call register_loader() to make sure the classLoader data gets created.
ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader);
--- a/src/hotspot/share/classfile/modules.hpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/modules.hpp Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 2018, 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
@@ -28,6 +28,7 @@
#include "memory/allocation.hpp"
#include "runtime/handles.hpp"
+class ModuleEntryTable;
class Symbol;
class Modules : AllStatic {
@@ -122,6 +123,7 @@
// Return TRUE iff package is defined by loader
static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
+ static ModuleEntryTable* get_module_entry_table(Handle h_loader);
};
#endif // SHARE_VM_CLASSFILE_MODULES_HPP
--- a/src/hotspot/share/classfile/sharedClassUtil.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/sharedClassUtil.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -93,6 +93,9 @@
case APP:
ClassLoader::trace_class_path("Expecting -Djava.class.path=", path);
break;
+ case MODULE:
+ ClassLoader::trace_class_path("Checking module path: ", path);
+ break;
default:
SharedPathsMiscInfo::print_path(out, type, path);
}
@@ -167,12 +170,13 @@
void SharedClassUtil::initialize(TRAPS) {
if (UseSharedSpaces) {
- int size = FileMapInfo::get_number_of_share_classpaths();
+ int size = FileMapInfo::get_number_of_shared_paths();
if (size > 0) {
SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
if (!DumpSharedSpaces) {
FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
- ClassLoaderExt::init_paths_start_index(header->_app_paths_start_index);
+ ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
+ ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
}
}
}
@@ -208,7 +212,7 @@
bool SharedClassUtil::is_classpath_entry_signed(int classpath_index) {
assert(classpath_index >= 0, "Sanity");
SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)
- FileMapInfo::shared_classpath(classpath_index);
+ FileMapInfo::shared_path(classpath_index);
return ent->_is_signed;
}
@@ -216,7 +220,8 @@
FileMapInfo::FileMapHeader::populate(mapinfo, alignment);
ClassLoaderExt::finalize_shared_paths_misc_info();
- _app_paths_start_index = ClassLoaderExt::app_paths_start_index();
+ _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
+ _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
_verify_local = BytecodeVerificationLocal;
_verify_remote = BytecodeVerificationRemote;
--- a/src/hotspot/share/classfile/sharedClassUtil.hpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/sharedClassUtil.hpp Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -34,10 +34,11 @@
class FileMapHeaderExt: public FileMapInfo::FileMapHeader {
public:
- jshort _app_paths_start_index; // Index of first app classpath entry
- bool _verify_local; // BytecodeVerificationLocal setting
- bool _verify_remote; // BytecodeVerificationRemote setting
- bool _has_platform_or_app_classes; // Archive contains app classes
+ jshort _app_class_paths_start_index; // Index of first app classpath entry
+ jshort _app_module_paths_start_index; // Index of first module path entry
+ bool _verify_local; // BytecodeVerificationLocal setting
+ bool _verify_remote; // BytecodeVerificationRemote setting
+ bool _has_platform_or_app_classes; // Archive contains app classes
FileMapHeaderExt() {
_has_platform_or_app_classes = true;
@@ -56,12 +57,14 @@
int _app_offset;
public:
enum {
- APP = 5
+ APP = 5,
+ MODULE = 6
};
virtual const char* type_name(int type) {
switch (type) {
case APP: return "APP";
+ case MODULE: return "MODULE";
default: return SharedPathsMiscInfo::type_name(type);
}
}
--- a/src/hotspot/share/classfile/systemDictionary.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -1217,7 +1217,7 @@
}
}
SharedClassPathEntry* ent =
- (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+ (SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
if (!Universe::is_module_initialized()) {
assert(ent != NULL && ent->is_modules_image(),
"Loading non-bootstrap classes before the module system is initialized");
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -92,7 +92,7 @@
Handle empty;
Handle manifest ;
if (shared_jar_manifest(shared_path_index) == NULL) {
- SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)FileMapInfo::shared_classpath(shared_path_index);
+ SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)FileMapInfo::shared_path(shared_path_index);
long size = ent->manifest_size();
if (size <= 0) {
return empty; // No manifest - return NULL handle
@@ -138,7 +138,7 @@
Handle url_h;
if (shared_jar_url(shared_path_index) == NULL) {
JavaValue result(T_OBJECT);
- const char* path = FileMapInfo::shared_classpath_name(shared_path_index);
+ const char* path = FileMapInfo::shared_path_name(shared_path_index);
Handle path_string = java_lang_String::create_from_str(path, CHECK_(url_h));
Klass* classLoaders_klass =
SystemDictionary::jdk_internal_loader_ClassLoaders_klass();
@@ -304,7 +304,7 @@
int index = ik->shared_classpath_index();
assert(index >= 0, "Sanity");
SharedClassPathEntryExt* ent =
- (SharedClassPathEntryExt*)FileMapInfo::shared_classpath(index);
+ (SharedClassPathEntryExt*)FileMapInfo::shared_path(index);
Symbol* class_name = ik->name();
if (ent->is_modules_image()) {
@@ -328,13 +328,13 @@
// For shared app/platform classes originated from JAR files on the class path:
// Each of the 3 SystemDictionaryShared::_shared_xxx arrays has the same length
// as the shared classpath table in the shared archive (see
- // FileMap::_classpath_entry_table in filemap.hpp for details).
+ // FileMap::_shared_path_table in filemap.hpp for details).
//
// If a shared InstanceKlass k is loaded from the class path, let
//
// index = k->shared_classpath_index():
//
- // FileMap::_classpath_entry_table[index] identifies the JAR file that contains k.
+ // FileMap::_shared_path_table[index] identifies the JAR file that contains k.
//
// k's protection domain is:
//
@@ -358,9 +358,7 @@
}
// Currently AppCDS only archives classes from the run-time image, the
-// -Xbootclasspath/a path, and the class path. The following rules need to be
-// revised when AppCDS is changed to archive classes from other code sources
-// in the future, for example the module path (specified by -p).
+// -Xbootclasspath/a path, the class path, and the module path.
//
// Check if a shared class can be loaded by the specific classloader. Following
// are the "visible" archived classes for different classloaders.
@@ -368,10 +366,10 @@
// NULL classloader:
// - see SystemDictionary::is_shared_class_visible()
// Platform classloader:
-// - Module class from "modules" jimage. ModuleEntry must be defined in the
+// - Module class from runtime image. ModuleEntry must be defined in the
// classloader.
-// App Classloader:
-// - Module class from "modules" jimage. ModuleEntry must be defined in the
+// App classloader:
+// - Module Class from runtime image and module path. ModuleEntry must be defined in the
// classloader.
// - Class from -cp. The class must have no PackageEntry defined in any of the
// boot/platform/app classloader, or must be in the unnamed module defined in the
@@ -386,10 +384,11 @@
TRAPS) {
assert(class_loader.not_null(), "Class loader should not be NULL");
assert(Universe::is_module_initialized(), "Module system is not initialized");
+ ResourceMark rm(THREAD);
int path_index = ik->shared_classpath_index();
SharedClassPathEntry* ent =
- (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+ (SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
if (SystemDictionary::is_platform_class_loader(class_loader())) {
assert(ent != NULL, "shared class for PlatformClassLoader should have valid SharedClassPathEntry");
@@ -400,7 +399,7 @@
// PackageEntry/ModuleEntry is found in the classloader. Check if the
// ModuleEntry's location agrees with the archived class' origination.
if (ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) {
- return true; // Module class from the "modules" jimage
+ return true; // Module class from the runtime image
}
}
} else if (SystemDictionary::is_system_class_loader(class_loader())) {
@@ -409,7 +408,8 @@
// The archived class is in the unnamed package. Currently, the boot image
// does not contain any class in the unnamed package.
assert(!ent->is_modules_image(), "Class in the unnamed package must be from the classpath");
- if (path_index >= ClassLoaderExt::app_paths_start_index()) {
+ if (path_index >= ClassLoaderExt::app_class_paths_start_index()) {
+ assert(path_index < ClassLoaderExt::app_module_paths_start_index(), "invalid path_index");
return true;
}
} else {
@@ -421,23 +421,37 @@
if (get_package_entry(pkg_name, ClassLoaderData::class_loader_data_or_null(SystemDictionary::java_platform_loader())) == NULL &&
get_package_entry(pkg_name, ClassLoaderData::the_null_class_loader_data()) == NULL) {
// The PackageEntry is not defined in any of the boot/platform/app classloaders.
- // The archived class must from -cp path and not from the run-time image.
- if (!ent->is_modules_image() && path_index >= ClassLoaderExt::app_paths_start_index()) {
+ // The archived class must from -cp path and not from the runtime image.
+ if (!ent->is_modules_image() && path_index >= ClassLoaderExt::app_class_paths_start_index() &&
+ path_index < ClassLoaderExt::app_module_paths_start_index()) {
return true;
}
}
} else if (mod_entry != NULL) {
- // The package/module is defined in the AppClassLoader. Currently we only
- // support archiving application module class from the run-time image.
+ // The package/module is defined in the AppClassLoader. We support
+ // archiving application module class from the runtime image or from
+ // a named module from a module path.
// Packages from the -cp path are in the unnamed_module.
- if ((ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) ||
- (pkg_entry->in_unnamed_module() && path_index >= ClassLoaderExt::app_paths_start_index())) {
+ if (ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) {
+ // shared module class from runtime image
+ return true;
+ } else if (pkg_entry->in_unnamed_module() && path_index >= ClassLoaderExt::app_class_paths_start_index() &&
+ path_index < ClassLoaderExt::app_module_paths_start_index()) {
+ // shared class from -cp
DEBUG_ONLY( \
ClassLoaderData* loader_data = class_loader_data(class_loader); \
- if (pkg_entry->in_unnamed_module()) \
- assert(mod_entry == loader_data->unnamed_module(), "the unnamed module is not defined in the classloader");)
-
+ assert(mod_entry == loader_data->unnamed_module(), "the unnamed module is not defined in the classloader");)
return true;
+ } else {
+ if(!pkg_entry->in_unnamed_module() &&
+ (path_index >= ClassLoaderExt::app_module_paths_start_index())&&
+ (path_index < FileMapInfo::get_number_of_shared_paths()) &&
+ (strcmp(ent->name(), ClassLoader::skip_uri_protocol(mod_entry->location()->as_C_string())) == 0)) {
+ // shared module class from module path
+ return true;
+ } else {
+ assert(path_index < FileMapInfo::get_number_of_shared_paths(), "invalid path_index");
+ }
}
}
}
--- a/src/hotspot/share/memory/filemap.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/memory/filemap.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -96,7 +96,7 @@
va_list ap;
va_start(ap, msg);
MetaspaceShared::set_archive_loading_failed();
- if (PrintSharedArchiveAndExit && _validating_classpath_entry_table) {
+ if (PrintSharedArchiveAndExit && _validating_shared_path_table) {
// If we are doing PrintSharedArchiveAndExit and some of the classpath entries
// do not validate, we can still continue "limping" to validate the remaining
// entries. No need to quit.
@@ -188,9 +188,9 @@
_max_heap_size = MaxHeapSize;
_narrow_klass_base = Universe::narrow_klass_base();
_narrow_klass_shift = Universe::narrow_klass_shift();
- _classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
- _classpath_entry_table = mapinfo->_classpath_entry_table;
- _classpath_entry_size = mapinfo->_classpath_entry_size;
+ _shared_path_table_size = mapinfo->_shared_path_table_size;
+ _shared_path_table = mapinfo->_shared_path_table;
+ _shared_path_entry_size = mapinfo->_shared_path_entry_size;
// The following fields are for sanity checks for whether this archive
// will function correctly with this JVM and the bootclasspath it's
@@ -231,12 +231,16 @@
strcpy(_name->data(), name);
}
-bool SharedClassPathEntry::validate() {
+bool SharedClassPathEntry::validate(bool is_class_path) {
struct stat st;
const char* name = this->name();
bool ok = true;
log_info(class, path)("checking shared classpath entry: %s", name);
- if (os::stat(name, &st) != 0) {
+ if (os::stat(name, &st) != 0 && is_class_path) {
+ // If the archived module path entry does not exist at runtime, it is not fatal
+ // (no need to invalid the shared archive) because the shared runtime visibility check
+ // filters out any archived module classes that do not have a matching runtime
+ // module path location.
FileMapInfo::fail_continue("Required classpath entry does not exist: %s", name);
ok = false;
} else if (is_dir()) {
@@ -266,7 +270,7 @@
it->push(&_manifest);
}
-void FileMapInfo::allocate_classpath_entry_table() {
+void FileMapInfo::allocate_shared_path_table() {
assert(DumpSharedSpaces, "Sanity");
Thread* THREAD = Thread::current();
@@ -279,12 +283,13 @@
size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); // assert ( should be 8 byte aligned??)
int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries();
int num_app_classpath_entries = ClassLoader::num_app_classpath_entries();
- int num_entries = num_boot_classpath_entries + num_app_classpath_entries;
+ int num_module_path_entries = ClassLoader::num_module_path_entries();
+ int num_entries = num_boot_classpath_entries + num_app_classpath_entries + num_module_path_entries;
size_t bytes = entry_size * num_entries;
- _classpath_entry_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
- _classpath_entry_table_size = num_entries;
- _classpath_entry_size = entry_size;
+ _shared_path_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
+ _shared_path_table_size = num_entries;
+ _shared_path_entry_size = entry_size;
// 1. boot class path
int i = 0;
@@ -292,7 +297,7 @@
while (cpe != NULL) {
const char* type = ((cpe == jrt) ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir"));
log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
- SharedClassPathEntry* ent = shared_classpath(i);
+ SharedClassPathEntry* ent = shared_path(i);
ent->init(cpe->name(), THREAD);
if (cpe != jrt) { // No need to do jimage.
EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
@@ -308,41 +313,66 @@
ClassPathEntry *acpe = ClassLoader::app_classpath_entries();
while (acpe != NULL) {
log_info(class, path)("add app shared path %s", acpe->name());
- SharedClassPathEntry* ent = shared_classpath(i);
+ SharedClassPathEntry* ent = shared_path(i);
ent->init(acpe->name(), THREAD);
EXCEPTION_MARK;
SharedClassUtil::update_shared_classpath(acpe, ent, THREAD);
acpe = acpe->next();
- i ++;
+ i++;
}
- assert(i == num_entries, "number of app class path entry mismatch");
+
+ // 3. module path
+ ClassPathEntry *mpe = ClassLoader::module_path_entries();
+ while (mpe != NULL) {
+ log_info(class, path)("add module path %s",mpe->name());
+ SharedClassPathEntry* ent = shared_path(i);
+ ent->init(mpe->name(), THREAD);
+ EXCEPTION_MARK;
+ SharedClassUtil::update_shared_classpath(mpe, ent, THREAD);
+ mpe = mpe->next();
+ i++;
+ }
+ assert(i == num_entries, "number of shared path entry mismatch");
}
-bool FileMapInfo::validate_classpath_entry_table() {
- _validating_classpath_entry_table = true;
+// This function should only be called during run time with UseSharedSpaces enabled.
+bool FileMapInfo::validate_shared_path_table() {
+ _validating_shared_path_table = true;
+
+ _shared_path_table = _header->_shared_path_table;
+ _shared_path_entry_size = _header->_shared_path_entry_size;
+ _shared_path_table_size = _header->_shared_path_table_size;
- int count = _header->_classpath_entry_table_size;
+ // Note: _app_module_paths_start_index may not have a valid value if the UseAppCDS flag
+ // wasn't enabled during dump time. Therefore, we need to use the smaller of
+ // _shared_path_table_size and _app_module_paths_start_index for the _app_module_paths_start_index.
+ FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
+ int module_paths_start_index = (header->_app_module_paths_start_index >= _shared_path_table_size) ?
+ _shared_path_table_size : header->_app_module_paths_start_index;
- _classpath_entry_table = _header->_classpath_entry_table;
- _classpath_entry_size = _header->_classpath_entry_size;
- _classpath_entry_table_size = _header->_classpath_entry_table_size;
+ int count = _shared_path_table_size;
for (int i=0; i<count; i++) {
- if (shared_classpath(i)->validate()) {
- log_info(class, path)("ok");
+ if (i < module_paths_start_index) {
+ if (shared_path(i)->validate()) {
+ log_info(class, path)("ok");
+ }
+ } else if (i >= module_paths_start_index) {
+ if (shared_path(i)->validate(false /* not a class path entry */)) {
+ log_info(class, path)("ok");
+ }
} else if (!PrintSharedArchiveAndExit) {
- _validating_classpath_entry_table = false;
- _classpath_entry_table = NULL;
- _classpath_entry_table_size = 0;
+ _validating_shared_path_table = false;
+ _shared_path_table = NULL;
+ _shared_path_table_size = 0;
return false;
}
}
- _validating_classpath_entry_table = false;
+ _validating_shared_path_table = false;
return true;
}
-
// Read the FileMapInfo information from the file.
bool FileMapInfo::init_from_file(int fd) {
@@ -925,18 +955,18 @@
}
void FileMapInfo::metaspace_pointers_do(MetaspaceClosure* it) {
- it->push(&_classpath_entry_table);
- for (int i=0; i<_classpath_entry_table_size; i++) {
- shared_classpath(i)->metaspace_pointers_do(it);
+ it->push(&_shared_path_table);
+ for (int i=0; i<_shared_path_table_size; i++) {
+ shared_path(i)->metaspace_pointers_do(it);
}
}
FileMapInfo* FileMapInfo::_current_info = NULL;
-Array<u8>* FileMapInfo::_classpath_entry_table = NULL;
-int FileMapInfo::_classpath_entry_table_size = 0;
-size_t FileMapInfo::_classpath_entry_size = 0x1234baad;
-bool FileMapInfo::_validating_classpath_entry_table = false;
+Array<u8>* FileMapInfo::_shared_path_table = NULL;
+int FileMapInfo::_shared_path_table_size = 0;
+size_t FileMapInfo::_shared_path_entry_size = 0x1234baad;
+bool FileMapInfo::_validating_shared_path_table = false;
// Open the shared archive file, read and validate the header
// information (version, boot classpath, etc.). If initialization
@@ -946,7 +976,7 @@
// Validation of the archive is done in two steps:
//
// [1] validate_header() - done here. This checks the header, including _paths_misc_info.
-// [2] validate_classpath_entry_table - this is done later, because the table is in the RW
+// [2] validate_shared_path_table - this is done later, because the table is in the RW
// region of the archive, which is not mapped yet.
bool FileMapInfo::initialize() {
assert(UseSharedSpaces, "UseSharedSpaces expected.");
@@ -980,6 +1010,7 @@
return crc;
}
+// This function should only be called during run time with UseSharedSpaces enabled.
bool FileMapInfo::FileMapHeader::validate() {
if (VerifySharedSpaces && compute_crc() != _crc) {
fail_continue("Header checksum verification failed.");
--- a/src/hotspot/share/memory/filemap.hpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/memory/filemap.hpp Tue Apr 10 11:43:40 2018 -0700
@@ -53,7 +53,7 @@
public:
void init(const char* name, TRAPS);
void metaspace_pointers_do(MetaspaceClosure* it);
- bool validate();
+ bool validate(bool is_class_path = true);
// The _timestamp only gets set for jar files and "modules" jimage.
bool is_jar_or_bootimage() {
@@ -85,10 +85,10 @@
size_t _file_offset;
private:
- static Array<u8>* _classpath_entry_table;
- static int _classpath_entry_table_size;
- static size_t _classpath_entry_size;
- static bool _validating_classpath_entry_table;
+ static Array<u8>* _shared_path_table;
+ static int _shared_path_table_size;
+ static size_t _shared_path_entry_size;
+ static bool _validating_shared_path_table;
// FileMapHeader describes the shared space data in the file to be
// mapped. This structure gets written to a file. It is not a class, so
@@ -153,7 +153,7 @@
// checking the validity of the archive and is deallocated after the archive is loaded.
//
// Note that the _paths_misc_info does NOT include information for JAR files
- // that existed during dump time. Their information is stored in _classpath_entry_table.
+ // that existed during dump time. Their information is stored in _shared_path_table.
int _paths_misc_info_size;
// The following is a table of all the class path entries that were used
@@ -167,9 +167,9 @@
// FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
// they should be removed from this table, to save space and to avoid spurious
// loading failures during runtime.
- int _classpath_entry_table_size;
- size_t _classpath_entry_size;
- Array<u8>* _classpath_entry_table;
+ int _shared_path_table_size;
+ size_t _shared_path_entry_size;
+ Array<u8>* _shared_path_table;
char* region_addr(int idx);
@@ -270,25 +270,26 @@
// Stop CDS sharing and unmap CDS regions.
static void stop_sharing_and_unmap(const char* msg);
- static void allocate_classpath_entry_table();
- bool validate_classpath_entry_table();
+ static void allocate_shared_path_table();
+ bool validate_shared_path_table();
- static SharedClassPathEntry* shared_classpath(int index) {
+ static SharedClassPathEntry* shared_path(int index) {
if (index < 0) {
return NULL;
}
- assert(index < _classpath_entry_table_size, "sanity");
- char* p = (char*)_classpath_entry_table->data();
- p += _classpath_entry_size * index;
+ assert(index < _shared_path_table_size, "sanity");
+ char* p = (char*)_shared_path_table->data();
+ p += _shared_path_entry_size * index;
return (SharedClassPathEntry*)p;
}
- static const char* shared_classpath_name(int index) {
+
+ static const char* shared_path_name(int index) {
assert(index >= 0, "Sanity");
- return shared_classpath(index)->name();
+ return shared_path(index)->name();
}
- static int get_number_of_share_classpaths() {
- return _classpath_entry_table_size;
+ static int get_number_of_shared_paths() {
+ return _shared_path_table_size;
}
private:
--- a/src/hotspot/share/memory/metaspaceShared.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/memory/metaspaceShared.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -1619,7 +1619,6 @@
void MetaspaceShared::prepare_for_dumping() {
Arguments::check_unsupported_dumping_properties();
ClassLoader::initialize_shared_path();
- FileMapInfo::allocate_classpath_entry_table();
}
// Preload classes from a list, populate the shared spaces and dump to a
@@ -2001,7 +2000,7 @@
(md_base = mapinfo->map_region(md, &md_top)) != NULL &&
(od_base = mapinfo->map_region(od, &od_top)) != NULL &&
(image_alignment == (size_t)os::vm_allocation_granularity()) &&
- mapinfo->validate_classpath_entry_table()) {
+ mapinfo->validate_shared_path_table()) {
// Success -- set up MetaspaceObj::_shared_metaspace_{base,top} for
// fast checking in MetaspaceShared::is_in_shared_metaspace() and
// MetaspaceObj::is_shared().
--- a/src/hotspot/share/oops/klass.hpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/oops/klass.hpp Tue Apr 10 11:43:40 2018 -0700
@@ -150,7 +150,7 @@
int _vtable_len;
private:
- // This is an index into FileMapHeader::_classpath_entry_table[], to
+ // This is an index into FileMapHeader::_shared_path_table[], to
// associate this class with the JAR file where it's loaded from during
// dump time. If a class is not loaded from the shared archive, this field is
// -1.
--- a/src/hotspot/share/runtime/arguments.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/runtime/arguments.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -1446,35 +1446,23 @@
}
#if INCLUDE_CDS
+const char* unsupported_properties[] = { "jdk.module.limitmods",
+ "jdk.module.upgrade.path",
+ "jdk.module.patch.0" };
+const char* unsupported_options[] = { "--limit-modules",
+ "--upgrade-module-path",
+ "--patch-module"
+ };
void Arguments::check_unsupported_dumping_properties() {
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
- const char* unsupported_properties[] = { "jdk.module.main",
- "jdk.module.limitmods",
- "jdk.module.path",
- "jdk.module.upgrade.path",
- "jdk.module.patch.0" };
- const char* unsupported_options[] = { "-m", // cannot use at dump time
- "--limit-modules", // ignored at dump time
- "--module-path", // ignored at dump time
- "--upgrade-module-path", // ignored at dump time
- "--patch-module" // ignored at dump time
- };
assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
- // If a vm option is found in the unsupported_options array with index less than the info_idx,
- // vm will exit with an error message. Otherwise, it will print an informational message if
- // -Xlog:cds is enabled.
- uint info_idx = 1;
+ // If a vm option is found in the unsupported_options array, vm will exit with an error message.
SystemProperty* sp = system_properties();
while (sp != NULL) {
for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
- if (i < info_idx) {
- vm_exit_during_initialization(
- "Cannot use the following option when dumping the shared archive", unsupported_options[i]);
- } else {
- log_info(cds)("Info: the %s option is ignored when dumping the shared archive",
- unsupported_options[i]);
- }
+ vm_exit_during_initialization(
+ "Cannot use the following option when dumping the shared archive", unsupported_options[i]);
}
}
sp = sp->next();
@@ -1485,6 +1473,20 @@
vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build");
}
}
+
+bool Arguments::check_unsupported_cds_runtime_properties() {
+ assert(UseSharedSpaces, "this function is only used with -Xshare:{on,auto}");
+ assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
+ for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
+ if (get_property(unsupported_properties[i]) != NULL) {
+ if (RequireSharedSpaces) {
+ warning("CDS is disabled when the %s option is specified.", unsupported_options[i]);
+ }
+ return true;
+ }
+ }
+ return false;
+}
#endif
//===========================================================================================================
@@ -3378,6 +3380,9 @@
if (UseSharedSpaces && patch_mod_javabase) {
no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched.");
}
+ if (UseSharedSpaces && !DumpSharedSpaces && check_unsupported_cds_runtime_properties()) {
+ FLAG_SET_DEFAULT(UseSharedSpaces, false);
+ }
#endif
#ifndef CAN_SHOW_REGISTERS_ON_ASSERT
--- a/src/hotspot/share/runtime/arguments.hpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/runtime/arguments.hpp Tue Apr 10 11:43:40 2018 -0700
@@ -703,6 +703,8 @@
static void check_unsupported_dumping_properties() NOT_CDS_RETURN;
+ static bool check_unsupported_cds_runtime_properties() NOT_CDS_RETURN;
+
static bool atojulong(const char *s, julong* result);
};
--- a/src/hotspot/share/runtime/thread.cpp Tue Apr 10 10:06:42 2018 -0400
+++ b/src/hotspot/share/runtime/thread.cpp Tue Apr 10 11:43:40 2018 -0700
@@ -3891,6 +3891,11 @@
// cache the system and platform class loaders
SystemDictionary::compute_java_loaders(CHECK_JNI_ERR);
+ if (DumpSharedSpaces) {
+ // capture the module path info from the ModuleEntryTable
+ ClassLoader::initialize_module_path(THREAD);
+ }
+
#if INCLUDE_JVMCI
if (force_JVMCI_intialization) {
JVMCIRuntime::force_initialization(CHECK_JNI_ERR);
--- a/test/hotspot/jtreg/runtime/appcds/JarBuilder.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/JarBuilder.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -32,9 +32,11 @@
*/
import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.compiler.CompilerUtils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.io.File;
+import java.nio.file.Path;
import java.util.ArrayList;
import sun.tools.jar.Main;
@@ -145,6 +147,21 @@
}
}
+ public static void createModularJar(String jarPath,
+ String classesDir,
+ String mainClass) throws Exception {
+ ArrayList<String> argList = new ArrayList<String>();
+ argList.add("--create");
+ argList.add("--file=" + jarPath);
+ if (mainClass != null) {
+ argList.add("--main-class=" + mainClass);
+ }
+ argList.add("-C");
+ argList.add(classesDir);
+ argList.add(".");
+ createJar(argList);
+ }
+
private static void createJar(ArrayList<String> args) {
if (DEBUG) printIterable("createJar args: ", args);
@@ -190,6 +207,23 @@
output.shouldHaveExitValue(0);
}
+ public static void compileModule(Path src,
+ Path dest,
+ String modulePathArg // arg to --module-path
+ ) throws Exception {
+ boolean compiled = false;
+ if (modulePathArg == null) {
+ compiled = CompilerUtils.compile(src, dest);
+ } else {
+ compiled = CompilerUtils.compile(src, dest,
+ "--module-path", modulePathArg);
+ }
+ if (!compiled) {
+ throw new RuntimeException("module did not compile");
+ }
+ }
+
+
public static void signJar() throws Exception {
String keyTool = JDKToolFinder.getJDKTool("keytool");
String jarSigner = JDKToolFinder.getJDKTool("jarsigner");
--- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java Tue Apr 10 11:43:40 2018 -0700
@@ -200,13 +200,18 @@
return new Result(opts, runWithArchive(opts));
}
-
public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar);
opts.addSuffix(suffix);
return runWithArchive(opts);
}
+ public static Result runWithModules(String prefix[], String upgrademodulepath, String modulepath,
+ String mid, String... testClassArgs) throws Exception {
+ AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath,
+ mid, testClassArgs);
+ return new Result(opts, runWithArchive(opts));
+ }
public static OutputAnalyzer execAuto(String... suffix) throws Exception {
AppCDSOptions opts = (new AppCDSOptions());
@@ -220,10 +225,9 @@
return runWithArchive(opts);
}
- public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath,
- String mid, String... testClassArgs)
- throws Exception {
+ private static AppCDSOptions makeModuleOptions(String prefix[], String upgrademodulepath, String modulepath,
+ String mid, String testClassArgs[]) {
AppCDSOptions opts = (new AppCDSOptions());
opts.addPrefix(prefix);
@@ -234,7 +238,14 @@
"-p", modulepath, "-m", mid);
}
opts.addSuffix(testClassArgs);
+ return opts;
+ }
+ public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath,
+ String mid, String... testClassArgs)
+ throws Exception {
+ AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath,
+ mid, testClassArgs);
return runWithArchive(opts);
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -40,20 +40,15 @@
public class CheckUnsupportedDumpingOptions {
private static final String[] jigsawOptions = {
- "-m",
"--limit-modules",
- "--module-path",
"--upgrade-module-path",
"--patch-module"
};
private static final String[] optionValues = {
"mymod",
- "mymod",
- "mydir",
".",
"java.naming=javax.naming.spi.NamingManger"
};
- private static final int infoIdx = 1;
public static void main(String[] args) throws Exception {
String source = "package javax.naming.spi; " +
@@ -71,31 +66,11 @@
String appClasses[] = {"Hello"};
for (int i = 0; i < jigsawOptions.length; i++) {
OutputAnalyzer output;
- if (i == 5) {
- // --patch-module
- output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables",
- jigsawOptions[i] + optionValues[i] + appJar);
- } else {
- output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables",
- jigsawOptions[i], optionValues[i]);
- }
- if (i < infoIdx) {
- output.shouldContain("Cannot use the following option " +
- "when dumping the shared archive: " + jigsawOptions[i])
- .shouldHaveExitValue(1);
- } else {
- output.shouldContain("Info: the " + jigsawOptions[i] +
- " option is ignored when dumping the shared archive");
- if (optionValues[i].equals("mymod")) {
- // java will throw FindException for a module
- // which cannot be found during init_phase2() of vm init
- output.shouldHaveExitValue(1)
- .shouldContain("java.lang.module.FindException: Module mymod not found");
- } else {
- output.shouldHaveExitValue(0);
- }
- }
+ output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables",
+ jigsawOptions[i], optionValues[i]);
+ output.shouldContain("Cannot use the following option " +
+ "when dumping the shared archive: " + jigsawOptions[i])
+ .shouldHaveExitValue(1);
}
}
}
-
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -69,8 +69,7 @@
private ArrayList<TestCase> testCaseTable = new ArrayList<TestCase>();
public static String infoDuringDump(String option) {
- return "Info: the " + option +
- " option is ignored when dumping the shared archive";
+ return "Cannot use the following option when dumping the shared archive: " + option;
}
public void runTests() throws Exception {
@@ -78,7 +77,7 @@
testCaseTable.add(new TestCase(
"basic: Basic dump and execute, to verify the test plumbing works",
"", "", 0,
- "", "", 0) );
+ "", "", 0, true) );
String bcpArg = "-Xbootclasspath/a:" +
TestCommon.getTestJar("hello_more.jar");
@@ -86,51 +85,50 @@
testCaseTable.add(new TestCase(
"Xbootclasspath/a: is OK for both dump and run time",
bcpArg, "", 0,
- bcpArg, "", 0) );
+ bcpArg, "", 0, true) );
testCaseTable.add(new TestCase(
"module-path-01: --module-path is ignored for dump time",
- "--module-path mods",
- infoDuringDump("--module-path"), 0,
- null, null, 0) );
+ "--module-path mods", "", 0,
+ null, null, 0, true) );
testCaseTable.add(new TestCase(
"module-path-02: --module-path is ok for run time",
"", "", 0,
- "--module-path mods", "", 0) );
+ "--module-path mods", "", 0, true) );
testCaseTable.add(new TestCase(
"add-modules-01: --add-modules is ok at dump time",
"--add-modules java.management",
"", 0,
- null, null, 0) );
+ null, null, 0, true) );
testCaseTable.add(new TestCase(
"add-modules-02: --add-modules is ok at run time",
"", "", 0,
- "--add-modules java.management", "", 0) );
+ "--add-modules java.management", "", 0, true) );
testCaseTable.add(new TestCase(
"limit-modules-01: --limit-modules is ignored at dump time",
"--limit-modules java.base",
- infoDuringDump("--limit-modules"), 0,
- null, null, 0) );
+ infoDuringDump("--limit-modules"), 1,
+ null, null, 0, true) );
testCaseTable.add(new TestCase(
"limit-modules-02: --limit-modules is ok at run time",
"", "", 0,
- "--limit-modules java.base", "", 0) );
+ "--limit-modules java.base", "", 0, false) );
testCaseTable.add(new TestCase(
"upgrade-module-path-01: --upgrade-module-path is ignored at dump time",
"--upgrade-module-path mods",
- infoDuringDump("--upgrade-module-path"), 0,
- null, null, 0) );
+ infoDuringDump("--upgrade-module-path"), 1,
+ null, null, 0, true) );
testCaseTable.add(new TestCase(
"-upgrade-module-path-module-path-02: --upgrade-module-path is ok at run time",
"", "", 0,
- "--upgrade-module-path mods", "", 0) );
+ "--upgrade-module-path mods", "", 0, false) );
for (TestCase tc : testCaseTable) tc.execute();
}
@@ -145,6 +143,7 @@
String runTimeArgs;
String runTimeExpectedOutput;
int runTimeExpectedExitValue;
+ boolean sharingOn;
private String appJar = TestCommon.getTestJar("hello.jar");
private String appClasses[] = {"Hello"};
@@ -152,7 +151,8 @@
public TestCase(String description,
String dumpTimeArgs, String dumpTimeExpectedOutput, int dumpTimeExpectedExitValue,
- String runTimeArgs, String runTimeExpectedOutput, int runTimeExpectedExitValue) {
+ String runTimeArgs, String runTimeExpectedOutput, int runTimeExpectedExitValue,
+ boolean sharingOn) {
this.description = description;
this.dumpTimeArgs = dumpTimeArgs;
@@ -161,6 +161,7 @@
this.runTimeArgs = runTimeArgs;
this.runTimeExpectedOutput = runTimeExpectedOutput;
this.runTimeExpectedExitValue = runTimeExpectedExitValue;
+ this.sharingOn = sharingOn;
}
@@ -183,7 +184,13 @@
OutputAnalyzer execOutput = TestCommon.exec(appJar, getRunOptions());
if (runTimeExpectedExitValue == 0) {
- TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World");
+ if (sharingOn) {
+ TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World");
+ } else {
+ execOutput.shouldHaveExitValue(0)
+ .shouldContain(runTimeExpectedOutput)
+ .shouldContain("Hello World");
+ }
} else {
execOutput.shouldMatch(dumpTimeExpectedOutput);
execOutput.shouldHaveExitValue(dumpTimeExpectedExitValue);
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java Tue Apr 10 11:43:40 2018 -0700
@@ -86,7 +86,8 @@
"--patch-module=java.naming=" + moduleJar,
"-Xlog:class+load",
"PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello");
- TestCommon.checkDump(output, "Loading classes to share");
+ output.shouldHaveExitValue(1)
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
String classPath = appJar + File.pathSeparator + classDir;
System.out.println("classPath: " + classPath);
@@ -96,9 +97,6 @@
"--patch-module=java.naming=" + moduleJar,
"-Xlog:class+load",
"PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello")
- .assertNormalExit(
- "I pass!",
- "Hello!",
- "Hello source: shared objects file");
+ .assertSilentlyDisabledCDS(0, "I pass!", "Hello!");
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java Tue Apr 10 11:43:40 2018 -0700
@@ -70,7 +70,8 @@
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.myspi.NamingManager");
- TestCommon.checkDump(output, "Preload Warning: Cannot find javax/naming/myspi/NamingManager");
+ output.shouldHaveExitValue(1)
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
TestCommon.run(
"-XX:+UnlockDiagnosticVMOptions",
@@ -78,6 +79,6 @@
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.myspi.NamingManager")
- .assertNormalExit("I pass!");
+ .assertSilentlyDisabledCDS(0, "I pass!");
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java Tue Apr 10 11:43:40 2018 -0700
@@ -62,41 +62,18 @@
JarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
moduleJar = TestCommon.getTestJar("javanaming.jar");
- // Case 1: --patch-module specified for dump time and run time
+ // Case 1: --patch-module specified for dump time
System.out.println("Case 1: --patch-module specified for dump time and run time");
OutputAnalyzer output =
TestCommon.dump(null,
TestCommon.list("javax/naming/spi/NamingManager"),
"--patch-module=java.naming=" + moduleJar,
"PatchMain", "javax.naming.spi.NamingManager");
- TestCommon.checkDump(output, "Loading classes to share");
-
- // javax.naming.spi.NamingManager is not patched at runtime
- TestCommon.run(
- "-XX:+UnlockDiagnosticVMOptions",
- "--patch-module=java.naming2=" + moduleJar,
- "-Xlog:class+path=info",
- "PatchMain", "javax.naming.spi.NamingManager")
- .assertNormalExit(o -> o.shouldNotContain("I pass!"));
+ output.shouldHaveExitValue(1)
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
- // Case 2: --patch-module specified for dump time but not for run time
- System.out.println("Case 2: --patch-module specified for dump time but not for run time");
- output =
- TestCommon.dump(null,
- TestCommon.list("javax/naming/spi/NamingManager"),
- "--patch-module=java.naming=" + moduleJar,
- "PatchMain", "javax.naming.spi.NamingManager");
- TestCommon.checkDump(output, "Loading classes to share");
-
- // javax.naming.spi.NamingManager is not patched at runtime
- TestCommon.run(
- "-XX:+UnlockDiagnosticVMOptions",
- "-Xlog:class+path=info",
- "PatchMain", "javax.naming.spi.NamingManager")
- .assertNormalExit(o -> o.shouldNotContain("I pass!"));
-
- // Case 3: --patch-module specified for run time but not for dump time
- System.out.println("Case 3: --patch-module specified for run time but not for dump time");
+ // Case 2: --patch-module specified for run time but not for dump time
+ System.out.println("Case 2: --patch-module specified for run time but not for dump time");
output =
TestCommon.dump(null,
TestCommon.list("javax/naming/spi/NamingManager"),
@@ -107,26 +84,9 @@
TestCommon.run(
"-XX:+UnlockDiagnosticVMOptions",
"--patch-module=java.naming=" + moduleJar,
- "-Xlog:class+path=info",
- "PatchMain", "javax.naming.spi.NamingManager")
- .assertNormalExit("I pass!");
-
- // Case 4: mismatched --patch-module entry counts between dump time and run time
- System.out.println("Case 4: mismatched --patch-module entry counts between dump time and run time");
- output =
- TestCommon.dump(null,
- TestCommon.list("javax/naming/spi/NamingManager"),
- "--patch-module=java.naming=" + moduleJar,
- "PatchMain", "javax.naming.spi.NamingManager");
- TestCommon.checkDump(output, "Loading classes to share");
-
- // javax.naming.spi.NamingManager is patched at runtime
- TestCommon.run(
- "-XX:+UnlockDiagnosticVMOptions",
- "--patch-module=java.naming=" + moduleJar,
"--patch-module=java.naming2=" + moduleJar,
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager")
- .assertNormalExit("I pass!");
+ .assertSilentlyDisabledCDS(0, "I pass!");
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -67,7 +67,7 @@
"--patch-module=java.naming=" + moduleJar,
"-Xlog:class+load",
"PatchMain", "javax.naming.spi.NamingManager")
- .shouldContain("Loading classes to share")
- .shouldHaveExitValue(0);
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module")
+ .shouldHaveExitValue(1);
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java Tue Apr 10 11:43:40 2018 -0700
@@ -62,7 +62,8 @@
TestCommon.dump(null, null,
"--patch-module=java.base=" + moduleJar,
"PatchMain", "java.lang.NewClass");
- TestCommon.checkDump(output, "Loading classes to share");
+ output.shouldHaveExitValue(1)
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
TestCommon.run(
"-XX:+UnlockDiagnosticVMOptions",
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -68,7 +68,8 @@
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager");
- TestCommon.checkDump(output, "Loading classes to share");
+ output.shouldHaveExitValue(1)
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
TestCommon.run(
"-XX:+UnlockDiagnosticVMOptions",
@@ -76,6 +77,6 @@
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager")
- .assertNormalExit("I pass!");
+ .assertSilentlyDisabledCDS(0, "I pass!");
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java Tue Apr 10 11:43:40 2018 -0700
@@ -88,7 +88,8 @@
"--patch-module=java.naming=" + moduleJar,
"-Xlog:class+load",
"PatchMain", "javax.naming.Reference", "mypackage.MyReference");
- TestCommon.checkDump(output, "Loading classes to share");
+ output.shouldHaveExitValue(1)
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
String classPath = appJar + File.pathSeparator + classDir;
System.out.println("classPath: " + classPath);
@@ -98,8 +99,6 @@
"--patch-module=java.naming=" + moduleJar,
"-Xlog:class+load",
"PatchMain", "javax.naming.Reference", "mypackage.MyReference")
- .assertNormalExit(
- "I pass!",
- "MyReference source: file:");
+ .assertSilentlyDisabledCDS(0, "MyReference source: file:", "I pass!");
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java Tue Apr 10 11:43:40 2018 -0700
@@ -87,7 +87,8 @@
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager");
- TestCommon.checkDump(output, "Loading classes to share");
+ output.shouldHaveExitValue(1)
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
TestCommon.run(
"-XX:+UnlockDiagnosticVMOptions",
@@ -95,6 +96,6 @@
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager")
- .assertNormalExit("I pass");
+ .assertSilentlyDisabledCDS(0, "I pass!");
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -145,29 +145,32 @@
// Test #3: A class in excluded package defined in boot module
// - should be loaded from the -Xbootclasspath/a by the boot classloader
public static void testBootAppendExcludedModuleClassWithoutAppCDS() throws Exception {
- CDSOptions opts = (new CDSOptions())
- .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
- "--limit-modules", "java.base")
- .setArchiveName(testArchiveName)
- .addSuffix(MAIN_CLASS, "Test #3", BOOT_APPEND_MODULE_CLASS, "true", "BOOT");
-
- CDSTestUtils.runWithArchiveAndCheck(opts);
+ TestCommon.run(
+ "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
+ "-Xlog:class+load=info",
+ "--limit-modules", "java.base",
+ MAIN_CLASS, "Test #3", BOOT_APPEND_MODULE_CLASS, "true", "BOOT")
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(".class.load. sun.nio.cs.ext.MyClass source:.*bootAppend.jar");
+ });
}
// Test #4: A shared class in excluded package that's archived from
// -Xbootclasspath/a
- // - should be loaded from the archive by the bootstrap classloader
+ // - should be loaded from the jar since AppCDS will be disabled with
+ // the --limit-modules option
public static void testBootAppendExcludedModuleClassWithAppCDS() throws Exception {
- OutputAnalyzer output = TestCommon.exec(
- appJar,
- "-Xbootclasspath/a:" + bootAppendJar,
+ TestCommon.run(
+ "-cp", appJar, "-Xbootclasspath/a:" + bootAppendJar,
+ "-Xlog:class+load=info",
"--limit-modules", "java.base",
- "-XX:+TraceClassLoading",
MAIN_CLASS,
- "Test #4", BOOT_APPEND_MODULE_CLASS, "true", "BOOT");
- TestCommon.checkExec(output);
- if (!TestCommon.isUnableToMap(output))
- output.shouldContain("[class,load] sun.nio.cs.ext.MyClass source: shared objects file");
+ "Test #4", BOOT_APPEND_MODULE_CLASS, "true", "BOOT")
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(".class.load. sun.nio.cs.ext.MyClass source:.*bootAppend.jar");
+ });
}
@@ -229,28 +232,28 @@
public static void testBootAppendAppExcludeModuleClassWithoutAppCDS()
throws Exception {
- CDSOptions opts = (new CDSOptions())
- .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
- "--limit-modules", "java.base")
- .setArchiveName(testArchiveName)
- .addSuffix(MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT");
-
- CDSTestUtils.runWithArchiveAndCheck(opts);
+ TestCommon.run(
+ "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
+ "-Xlog:class+load=info",
+ "--limit-modules", "java.base",
+ MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT")
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+ });
}
// Test #10: A shared class in excluded package defined in jimage app module
// - should be loaded from the -Xbootclasspath/a with AppCDS
public static void testBootAppendAppExcludeModuleClassAppCDS() throws Exception {
- OutputAnalyzer output = TestCommon.exec(
- appJar,
- "-Xbootclasspath/a:" + bootAppendJar,
- "-XX:+TraceClassLoading",
+ TestCommon.run(
+ "-cp", appJar, "-Xbootclasspath/a:" + bootAppendJar,
+ "-Xlog:class+load=info",
"--limit-modules", "java.base",
- MAIN_CLASS,
- "Test #10", APP_MODULE_CLASS, "true", "BOOT");
- TestCommon.checkExec(output);
-
- if (!TestCommon.isUnableToMap(output))
- output.shouldContain("[class,load] com.sun.tools.javac.Main2 source: shared objects file");
+ MAIN_CLASS, "Test #10", APP_MODULE_CLASS, "true", "BOOT")
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+ });
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java Tue Apr 10 11:43:40 2018 -0700
@@ -89,13 +89,15 @@
argsList.add("useAppLoader");
opts = new String[argsList.size()];
opts = argsList.toArray(opts);
- TestCommon.run(opts).assertNormalExit(EXPECTED_EXCEPTION);
+ TestCommon.run(opts)
+ .assertSilentlyDisabledCDS(0, EXPECTED_EXCEPTION);
// case 4: load class in bootclasspath using boot loader with '--limit-modules java.base'
argsList.remove(argsList.size() - 1);
argsList.add("useBootLoader");
opts = new String[argsList.size()];
opts = argsList.toArray(opts);
- TestCommon.run(opts).assertNormalExit(EXPECTED_EXCEPTION);
+ TestCommon.run(opts)
+ .assertSilentlyDisabledCDS(0, EXPECTED_EXCEPTION);
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -65,11 +65,22 @@
// Make sure we got the expected defining ClassLoader
testLoader(clazz, expectedLoaders[i]);
- // Make sure the class is in the shared space
- if (!wb.isSharedClass(clazz)) {
- throw new RuntimeException(clazz.getName() +
- ".class should be in the shared space. " +
- "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName());
+ // Make sure the class is not in the shared space
+ // because CDS is disabled with --limit-modules during run time.
+ if (excludeModIdx != -1) {
+ if (wb.isSharedClass(clazz)) {
+ throw new RuntimeException(clazz.getName() +
+ ".class should not be in the shared space. " +
+ "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName());
+ }
+ } else {
+ // class should be in the shared space if --limit-modules
+ // isn't specified during run time
+ if (!wb.isSharedClass(clazz)) {
+ throw new RuntimeException(clazz.getName() +
+ ".class should be in the shared space. " +
+ "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName());
+ }
}
}
clazz = null;
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -150,14 +150,14 @@
}
}
}
- output = TestCommon.exec(
- appJar + File.pathSeparator + helperJar,
+ TestCommon.run(
+ "-cp", appJar + File.pathSeparator + helperJar,
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", bootClassPath,
"--limit-modules", limitMods,
"LimitModsHelper",
BOOT_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, APP_ARCHIVE_CLASS,
- Integer.toString(excludeModIdx)); // last 4 args passed to test
- TestCommon.checkExec(output);
+ Integer.toString(excludeModIdx)) // last 4 args passed to test
+ .assertSilentlyDisabledCDS(0);
limitMods = null;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddModules.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018, 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
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ * jdk.jartool/sun.tools.jar
+ * jdk.jlink
+ * @run main AddModules
+ * @summary sanity test the --add-modules option
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class AddModules {
+
+ private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // the module name of the test module
+ private static final String MAIN_MODULE1 = "com.greetings";
+ private static final String MAIN_MODULE2 = "com.hello";
+ private static final String SUB_MODULE = "org.astro";
+
+ // the module main class
+ private static final String MAIN_CLASS1 = "com.greetings.Main";
+ private static final String MAIN_CLASS2 = "com.hello.Main";
+ private static final String APP_CLASS = "org.astro.World";
+
+ private static Path moduleDir = null;
+ private static Path subJar = null;
+ private static Path mainJar1 = null;
+ private static Path mainJar2 = null;
+
+ public static void buildTestModule() throws Exception {
+
+ // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(SUB_MODULE),
+ MODS_DIR.resolve(SUB_MODULE),
+ null);
+
+ // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE1),
+ MODS_DIR.resolve(MAIN_MODULE1),
+ MODS_DIR.toString());
+
+ JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE2),
+ MODS_DIR.resolve(MAIN_MODULE2),
+ MODS_DIR.toString());
+
+ moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+ subJar = moduleDir.resolve(SUB_MODULE + ".jar");
+ String classes = MODS_DIR.resolve(SUB_MODULE).toString();
+ JarBuilder.createModularJar(subJar.toString(), classes, null);
+
+ mainJar1 = moduleDir.resolve(MAIN_MODULE1 + ".jar");
+ classes = MODS_DIR.resolve(MAIN_MODULE1).toString();
+ JarBuilder.createModularJar(mainJar1.toString(), classes, MAIN_CLASS1);
+
+ mainJar2 = moduleDir.resolve(MAIN_MODULE2 + ".jar");
+ classes = MODS_DIR.resolve(MAIN_MODULE2).toString();
+ JarBuilder.createModularJar(mainJar2.toString(), classes, MAIN_CLASS2);
+
+ }
+
+ public static void main(String... args) throws Exception {
+ // compile the modules and create the modular jar files
+ buildTestModule();
+ String appClasses[] = {MAIN_CLASS1, MAIN_CLASS2, APP_CLASS};
+ // create an archive with the classes in the modules built in the
+ // previous step
+ OutputAnalyzer output = TestCommon.createArchive(
+ null, appClasses,
+ "--module-path", moduleDir.toString(),
+ "--add-modules",
+ MAIN_MODULE1 + "," + MAIN_MODULE2);
+ TestCommon.checkDump(output);
+ String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace"};
+
+ // run the com.greetings module with the archive with the --module-path
+ // the same as the one during dump time.
+ // The classes should be loaded from the archive.
+ TestCommon.runWithModules(prefix,
+ null, // --upgrade-module-path
+ moduleDir.toString(), // --module-path
+ MAIN_MODULE1) // -m
+ .assertNormalExit(out -> {
+ out.shouldContain("[class,load] com.greetings.Main source: shared objects file")
+ .shouldContain("[class,load] org.astro.World source: shared objects file");
+ });
+
+ // run the com.hello module with the archive with the --module-path
+ // the same as the one during dump time.
+ // The classes should be loaded from the archive.
+ TestCommon.runWithModules(prefix,
+ null, // --upgrade-module-path
+ moduleDir.toString(), // --module-path
+ MAIN_MODULE2) // -m
+ .assertNormalExit(out -> {
+ out.shouldContain("[class,load] com.hello.Main source: shared objects file")
+ .shouldContain("[class,load] org.astro.World source: shared objects file");
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, 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
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ * jdk.jartool/sun.tools.jar
+ * jdk.jlink
+ * @run main AddOpens
+ * @summary sanity test the --add-opens option
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class AddOpens {
+
+ private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // the module name of the test module
+ private static final String TEST_MODULE1 = "com.simple";
+
+ // the module main class
+ private static final String MAIN_CLASS = "com.simple.Main";
+
+ private static Path moduleDir = null;
+ private static Path moduleDir2 = null;
+ private static Path destJar = null;
+
+ public static void buildTestModule() throws Exception {
+
+ // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.toString());
+
+ moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+ moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+
+ Path srcJar = moduleDir.resolve(TEST_MODULE1 + ".jar");
+ destJar = moduleDir2.resolve(TEST_MODULE1 + ".jar");
+ String classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+ JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS);
+ Files.copy(srcJar, destJar);
+
+ }
+
+ public static void main(String... args) throws Exception {
+ // compile the modules and create the modular jar files
+ buildTestModule();
+ String appClasses[] = {MAIN_CLASS};
+ // create an archive with both -cp and --module-path in the command line.
+ // Only the class in the modular jar in the --module-path will be archived;
+ // the class in the modular jar in the -cp won't be archived.
+ OutputAnalyzer output = TestCommon.createArchive(
+ destJar.toString(), appClasses,
+ "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1);
+ TestCommon.checkDump(output);
+
+ // run with the archive using the same command line as in dump time
+ // plus the "--add-opens java.base/java.lang=com.simple" option.
+ // The main class should be loaded from the archive.
+ // The setaccessible(true) on the ClassLoader.defineClass method should
+ // be successful.
+ TestCommon.run( "-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--add-opens", "java.base/java.lang=" + TEST_MODULE1,
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1, "with_add_opens")
+ .assertNormalExit(
+ "[class,load] com.simple.Main source: shared objects file",
+ "method.setAccessible succeeded!");
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddReads.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018, 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
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ * jdk.jartool/sun.tools.jar
+ * jdk.jlink
+ * @run main AddReads
+ * @summary sanity test the --add-reads option
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.Asserts;
+
+public class AddReads {
+
+ private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // the module name of the test module
+ private static final String MAIN_MODULE = "com.norequires";
+ private static final String SUB_MODULE = "org.astro";
+
+ // the module main class
+ private static final String MAIN_CLASS = "com.norequires.Main";
+ private static final String APP_CLASS = "org.astro.World";
+
+ private static Path moduleDir = null;
+ private static Path subJar = null;
+ private static Path mainJar = null;
+
+ public static void buildTestModule() throws Exception {
+
+ // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(SUB_MODULE),
+ MODS_DIR.resolve(SUB_MODULE),
+ null);
+
+ Asserts.assertTrue(CompilerUtils
+ .compile(SRC_DIR.resolve(MAIN_MODULE),
+ MODS_DIR.resolve(MAIN_MODULE),
+ "-cp", MODS_DIR.resolve(SUB_MODULE).toString(),
+ "--add-reads", "com.norequires=ALL-UNNAMED"));
+
+ moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+ subJar = moduleDir.resolve(SUB_MODULE + ".jar");
+ String classes = MODS_DIR.resolve(SUB_MODULE).toString();
+ JarBuilder.createModularJar(subJar.toString(), classes, null);
+
+ mainJar = moduleDir.resolve(MAIN_MODULE + ".jar");
+ classes = MODS_DIR.resolve(MAIN_MODULE).toString();
+ JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS);
+ }
+
+ public static void main(String... args) throws Exception {
+ // compile the modules and create the modular jar files
+ buildTestModule();
+ String appClasses[] = {MAIN_CLASS, APP_CLASS};
+ // create an archive with the classes in the modules built in the
+ // previous step
+ OutputAnalyzer output = TestCommon.createArchive(
+ null, appClasses,
+ "--module-path", moduleDir.toString(),
+ "--add-modules", SUB_MODULE,
+ "--add-reads", "com.norequires=org.astro",
+ "-m", MAIN_MODULE);
+ TestCommon.checkDump(output);
+ String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace",
+ "--add-modules", SUB_MODULE,
+ "--add-reads", "com.norequires=org.astro"};
+
+ // run the com.norequires module with the archive with the same args
+ // used during dump time.
+ // The classes should be loaded from the archive.
+ TestCommon.runWithModules(prefix,
+ null, // --upgrade-module-path
+ moduleDir.toString(), // --module-path
+ MAIN_MODULE) // -m
+ .assertNormalExit(out -> {
+ out.shouldContain("[class,load] com.norequires.Main source: shared objects file")
+ .shouldContain("[class,load] org.astro.World source: shared objects file");
+ });
+
+ // create an archive with -cp pointing to the jar file containing the
+ // org.astro module and --module-path pointing to the main module
+ output = TestCommon.createArchive(
+ subJar.toString(), appClasses,
+ "--module-path", moduleDir.toString(),
+ "--add-modules", SUB_MODULE,
+ "--add-reads", "com.norequires=org.astro",
+ "-m", MAIN_MODULE);
+ TestCommon.checkDump(output);
+ // run the com.norequires module with the archive with the sub-module
+ // in the -cp and with -add-reads=com.norequires=ALL-UNNAMED
+ // The main class should be loaded from the archive.
+ // The org.astro.World should be loaded from the jar.
+ String prefix2[] = {"-cp", subJar.toString(), "-Xlog:class+load=trace",
+ "--add-reads", "com.norequires=ALL-UNNAMED"};
+ TestCommon.runWithModules(prefix2,
+ null, // --upgrade-module-path
+ moduleDir.toString(), // --module-path
+ MAIN_MODULE) // -m
+ .assertNormalExit(out -> {
+ out.shouldContain("[class,load] com.norequires.Main source: shared objects file")
+ .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+ });
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2018, 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
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ * jdk.jartool/sun.tools.jar
+ * jdk.jlink
+ * @run main ExportModule
+ * @summary Tests involve exporting a module from the module path to a jar in the -cp.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.Asserts;
+
+public class ExportModule {
+
+ private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // the module name of the test module
+ private static final String TEST_MODULE1 = "com.greetings";
+ private static final String TEST_MODULE2 = "org.astro";
+
+ // unnamed module package name
+ private static final String PKG_NAME = "com.nomodule";
+
+ // the module main class
+ private static final String MAIN_CLASS = "com.greetings.Main";
+ private static final String APP_CLASS = "org.astro.World";
+
+ // unnamed module main class
+ private static final String UNNAMED_MAIN = "com.nomodule.Main";
+
+ private static Path moduleDir = null;
+ private static Path moduleDir2 = null;
+ private static Path appJar = null;
+ private static Path appJar2 = null;
+
+ public static void buildTestModule() throws Exception {
+
+ // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE2),
+ MODS_DIR.resolve(TEST_MODULE2),
+ null);
+
+ // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.toString());
+
+ moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+ Path jar = moduleDir.resolve(TEST_MODULE2 + ".jar");
+ String classes = MODS_DIR.resolve(TEST_MODULE2).toString();
+ JarBuilder.createModularJar(jar.toString(), classes, null);
+
+ moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+ appJar = moduleDir2.resolve(TEST_MODULE1 + ".jar");
+ classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+ JarBuilder.createModularJar(appJar.toString(), classes, MAIN_CLASS);
+
+ // build a non-modular jar containing the main class which
+ // requires the org.astro package
+ boolean compiled
+ = CompilerUtils.compile(SRC_DIR.resolve(PKG_NAME),
+ MODS_DIR.resolve(PKG_NAME),
+ "--module-path", MODS_DIR.toString(),
+ "--add-modules", TEST_MODULE2,
+ "--add-exports", "org.astro/org.astro=ALL-UNNAMED");
+ Asserts.assertTrue(compiled, "test package did not compile");
+
+ appJar2 = moduleDir2.resolve(PKG_NAME + ".jar");
+ classes = MODS_DIR.resolve(PKG_NAME).toString();
+ JarBuilder.createModularJar(appJar2.toString(), classes, null);
+ }
+
+ public static void main(String... args) throws Exception {
+ // compile the modules and create the modular jar files
+ buildTestModule();
+ String appClasses[] = {MAIN_CLASS, APP_CLASS};
+ // create an archive with the class in the org.astro module built in the
+ // previous step and the main class from the modular jar in the -cp
+ // note: the main class is in the modular jar in the -cp which requires
+ // the module in the --module-path
+ OutputAnalyzer output = TestCommon.createArchive(
+ appJar.toString(), appClasses,
+ "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+ "--module-path", moduleDir.toString(),
+ "--add-modules", TEST_MODULE2, MAIN_CLASS);
+ TestCommon.checkDump(output);
+
+ // run it using the archive
+ // both the main class and the class from the org.astro module should
+ // be loaded from the archive
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", appJar.toString(),
+ "--module-path", moduleDir.toString(),
+ "--add-modules", TEST_MODULE2, MAIN_CLASS)
+ .assertNormalExit(
+ "[class,load] org.astro.World source: shared objects file",
+ "[class,load] com.greetings.Main source: shared objects file");
+
+ String appClasses2[] = {UNNAMED_MAIN, APP_CLASS};
+ // create an archive with the main class from a non-modular jar in the
+ // -cp and the class from the org.astro module
+ // note: the org.astro package needs to be exported to "ALL-UNNAMED"
+ // module since the jar in the -cp is a non-modular jar and thus it is
+ // unnmaed.
+ output = TestCommon.createArchive(
+ appJar2.toString(), appClasses2,
+ "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+ "--module-path", moduleDir.toString(),
+ "--add-modules", TEST_MODULE2,
+ "--add-exports", "org.astro/org.astro=ALL-UNNAMED",
+ UNNAMED_MAIN);
+ TestCommon.checkDump(output);
+
+ // both the main class and the class from the org.astro module should
+ // be loaded from the archive
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", appJar2.toString(),
+ "--module-path", moduleDir.toString(),
+ "--add-modules", TEST_MODULE2,
+ "--add-exports", "org.astro/org.astro=ALL-UNNAMED",
+ UNNAMED_MAIN)
+ .assertNormalExit(
+ "[class,load] org.astro.World source: shared objects file",
+ "[class,load] com.nomodule.Main source: shared objects file");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2018, 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 JvmtiEnv::AddToBootstrapClassLoaderSearch and JvmtiEnv::AddToSystemClassLoaderSearch should disable AppCDS
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * jdk.jartool/sun.tools.jar
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @compile ../../test-classes/JvmtiApp.java
+ * @run main JvmtiAddPath
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.process.OutputAnalyzer;
+import sun.hotspot.WhiteBox;
+
+public class JvmtiAddPath {
+ static String use_whitebox_jar;
+ static String[] no_extra_matches = {};
+ static String[] check_appcds_enabled = {
+ "[class,load] ExtraClass source: shared object"
+ };
+ static String[] check_appcds_disabled = {
+ "[class,load] ExtraClass source: file:"
+ };
+
+ private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // the module name of the test module
+ private static final String TEST_MODULE1 = "com.simple";
+
+ // the module main class
+ private static final String MAIN_CLASS = "com.simple.Main";
+
+ private static Path moduleDir = null;
+ private static Path mainJar = null;
+
+ public static void buildTestModule() throws Exception {
+
+ // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.toString());
+
+ moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+
+ mainJar = moduleDir.resolve(TEST_MODULE1 + ".jar");
+ String classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+ JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS);
+ }
+
+ static void run(String cp, String... args) throws Exception {
+ run(no_extra_matches, cp, args);
+ }
+
+ static void run(String[] extra_matches, String cp, String... args) throws Exception {
+ String[] opts = {"-cp", cp, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", use_whitebox_jar};
+ opts = TestCommon.concat(opts, args);
+ TestCommon.run(opts).assertNormalExit(extra_matches);
+ }
+
+ public static void main(String[] args) throws Exception {
+ buildTestModule();
+ JarBuilder.build("jvmti_app", "JvmtiApp", "ExtraClass");
+ JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
+
+ // In all the test cases below, appJar does not contain Hello.class. Instead, we
+ // append JAR file(s) that contain Hello.class to the boot classpath, the app
+ // classpath, or both, and verify that Hello.class is loaded by the expected ClassLoader.
+ String appJar = TestCommon.getTestJar("jvmti_app.jar"); // contains JvmtiApp.class
+ String addappJar = mainJar.toString(); // contains Main.class
+ String addbootJar = mainJar.toString(); // contains Main.class
+ String twoAppJars = appJar + File.pathSeparator + addappJar;
+ String modulePath = "--module-path=" + moduleDir.toString();
+ String wbJar = TestCommon.getTestJar("WhiteBox.jar");
+ use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
+
+ OutputAnalyzer output = TestCommon.createArchive(
+ appJar,
+ TestCommon.list("JvmtiApp", "ExtraClass", MAIN_CLASS),
+ use_whitebox_jar,
+ "-Xlog:class+load=trace",
+ modulePath);
+ TestCommon.checkDump(output);
+
+ System.out.println("Test case 1: not adding module path - Hello.class should not be found");
+ run(check_appcds_enabled, appJar,
+ "-Xlog:class+load", "JvmtiApp", "noadd", MAIN_CLASS); // appcds should be enabled
+
+ System.out.println("Test case 2: add to boot classpath only - should find Hello.class in boot loader");
+ run(check_appcds_disabled, appJar,
+ "-Xlog:class+load=trace",
+ modulePath,
+ "JvmtiApp", "bootonly", addbootJar, MAIN_CLASS); // appcds should be disabled
+
+ System.out.println("Test case 3: add to app classpath only - should find Hello.class in app loader");
+ run(appJar, modulePath,
+ "JvmtiApp", "apponly", addappJar, MAIN_CLASS);
+
+ System.out.println("Test case 4: add to boot and app paths - should find Hello.class in boot loader");
+ run(appJar, modulePath,
+ "JvmtiApp", "appandboot", addbootJar, addappJar, MAIN_CLASS);
+
+ System.out.println("Test case 5: add to app using -cp, but add to boot using JVMTI - should find Hello.class in boot loader");
+ run(appJar, modulePath,
+ "JvmtiApp", "bootonly", addappJar, MAIN_CLASS);
+
+ System.out.println("Test case 6: add to app using AppCDS, but add to boot using JVMTI - should find Hello.class in boot loader");
+ output = TestCommon.createArchive(
+ appJar, TestCommon.list("JvmtiApp", "ExtraClass"),
+ use_whitebox_jar,
+ "-Xlog:class+load=trace",
+ modulePath);
+ TestCommon.checkDump(output);
+ run(twoAppJars, modulePath,
+ "JvmtiApp", "bootonly", addappJar, MAIN_CLASS);
+
+ System.out.println("Test case 7: add to app using AppCDS, no JVMTI calls - should find Hello.class in app loader");
+ run(twoAppJars, modulePath,
+ "JvmtiApp", "noadd-appcds", MAIN_CLASS);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2018, 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
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ * jdk.jartool/sun.tools.jar
+ * jdk.jlink
+ * @run main MainModuleOnly
+ * @summary Test some scenarios with a main modular jar specified in the --module-path and -cp options in the command line.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class MainModuleOnly {
+
+ private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // the module name of the test module
+ private static final String TEST_MODULE1 = "com.simple";
+
+ // the module main class
+ private static final String MAIN_CLASS = "com.simple.Main";
+
+ private static Path moduleDir = null;
+ private static Path moduleDir2 = null;
+ private static Path destJar = null;
+
+ public static void buildTestModule() throws Exception {
+
+ // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.resolve(TEST_MODULE1),
+ MODS_DIR.toString());
+
+
+ moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+ moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+
+ Path srcJar = moduleDir.resolve(TEST_MODULE1 + ".jar");
+ destJar = moduleDir2.resolve(TEST_MODULE1 + ".jar");
+ String classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+ JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS);
+ Files.copy(srcJar, destJar);
+
+ }
+
+ public static void main(String... args) throws Exception {
+ // compile the modules and create the modular jar files
+ buildTestModule();
+ String appClasses[] = {MAIN_CLASS};
+ // create an archive with both -cp and --module-path in the command line.
+ // Only the class in the modular jar in the --module-path will be archived;
+ // the class in the modular jar in the -cp won't be archived.
+ OutputAnalyzer output = TestCommon.createArchive(
+ destJar.toString(), appClasses,
+ "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1);
+ TestCommon.checkDump(output);
+
+ // run with the archive using the same command line as in dump time.
+ // The main class should be loaded from the archive.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1)
+ .assertNormalExit("[class,load] com.simple.Main source: shared objects file");
+
+ // run with the archive with the main class name inserted before the -m.
+ // The main class name will be picked up before the module name. So the
+ // main class should be loaded from the jar in the -cp.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--module-path", moduleDir.toString(),
+ MAIN_CLASS, "-m", TEST_MODULE1)
+ .assertNormalExit(out ->
+ out.shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar"));
+
+ // run with the archive with exploded module. Since during dump time, we
+ // only archive classes from the modular jar in the --module-path, the
+ // main class should be loaded from the exploded module directory.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--module-path", MODS_DIR.toString(),
+ "-m", TEST_MODULE1 + "/" + MAIN_CLASS)
+ .assertNormalExit(out -> {
+ out.shouldMatch(".class.load. com.simple.Main source:.*com.simple")
+ .shouldContain(MODS_DIR.toString());
+ });
+
+ // run with the archive with the --upgrade-module-path option.
+ // CDS will be disabled with this options and the main class will be
+ // loaded from the modular jar.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--upgrade-module-path", moduleDir.toString(),
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1)
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch("CDS is disabled when the.*option is specified")
+ .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar");
+ });
+ // run with the archive with the --limit-modules option.
+ // CDS will be disabled with this options and the main class will be
+ // loaded from the modular jar.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--limit-modules", "java.base," + TEST_MODULE1,
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1)
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch("CDS is disabled when the.*option is specified")
+ .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar");
+ });
+ // run with the archive with the --patch-module option.
+ // CDS will be disabled with this options and the main class will be
+ // loaded from the modular jar.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--patch-module", TEST_MODULE1 + "=" + MODS_DIR.toString(),
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1)
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch("CDS is disabled when the.*option is specified")
+ .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar");
+ });
+ // modify the timestamp of the jar file
+ (new File(destJar.toString())).setLastModified(System.currentTimeMillis() + 2000);
+ // run with the archive and the jar with modified timestamp.
+ // It should fail due to timestamp of the jar doesn't match the one
+ // used during dump time.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", destJar.toString(),
+ "--module-path", moduleDir.toString(),
+ "-m", TEST_MODULE1)
+ .assertAbnormalExit(
+ "A jar/jimage file is not the one used while building the shared archive file:");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ModulePathAndCP.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2018, 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
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ * jdk.jartool/sun.tools.jar
+ * jdk.jlink
+ * @run main ModulePathAndCP
+ * @summary 2 sets of tests: one with only --module-path in the command line;
+ * another with both -cp and --module-path in the command line.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class ModulePathAndCP {
+
+ private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // the module name of the test module
+ private static final String MAIN_MODULE = "com.greetings";
+ private static final String APP_MODULE = "org.astro";
+
+ // the module main class
+ private static final String MAIN_CLASS = "com.greetings.Main";
+ private static final String APP_CLASS = "org.astro.World";
+
+ private static Path moduleDir = null;
+ private static Path moduleDir2 = null;
+ private static Path subJar = null;
+ private static Path mainJar = null;
+ private static Path destJar = null;
+
+ public static void buildTestModule() throws Exception {
+
+ // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(APP_MODULE),
+ MODS_DIR.resolve(APP_MODULE),
+ null);
+
+ // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+ JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE),
+ MODS_DIR.resolve(MAIN_MODULE),
+ MODS_DIR.toString());
+
+ moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+ moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+ subJar = moduleDir.resolve(APP_MODULE + ".jar");
+ destJar = moduleDir2.resolve(APP_MODULE + ".jar");
+ String classes = MODS_DIR.resolve(APP_MODULE).toString();
+ JarBuilder.createModularJar(subJar.toString(), classes, null);
+ Files.copy(subJar, destJar);
+
+ mainJar = moduleDir.resolve(MAIN_MODULE + ".jar");
+ Path mainJar2 = moduleDir2.resolve(MAIN_MODULE + ".jar");
+ classes = MODS_DIR.resolve(MAIN_MODULE).toString();
+ JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS);
+ Files.copy(mainJar, mainJar2);
+
+ }
+
+ public static void main(String... args) throws Exception {
+ // compile the modules and create the modular jar files
+ buildTestModule();
+ String appClasses[] = {MAIN_CLASS, APP_CLASS};
+ // create an archive with the classes in the modules built in the
+ // previous step
+ OutputAnalyzer output = TestCommon.createArchive(
+ null, appClasses,
+ "--module-path", moduleDir.toString(),
+ "-m", MAIN_MODULE);
+ TestCommon.checkDump(output);
+ String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace"};
+
+ // run with the archive with the --module-path the same as the one during
+ // dump time. The classes should be loaded from the archive.
+ TestCommon.runWithModules(prefix,
+ null, // --upgrade-module-path
+ moduleDir.toString(), // --module-path
+ MAIN_MODULE) // -m
+ .assertNormalExit(out -> {
+ out.shouldContain("[class,load] com.greetings.Main source: shared objects file")
+ .shouldContain("[class,load] org.astro.World source: shared objects file");
+ });
+
+ // run with the archive with the --module-path different from the one during
+ // dump time. The classes should be loaded from the jar files.
+ TestCommon.runWithModules(prefix,
+ null, // --upgrade-module-path
+ moduleDir2.toString(), // --module-path
+ MAIN_MODULE) // -m
+ .assertNormalExit(out -> {
+ out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar")
+ .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+ });
+
+ // create an archive with modular jar files in both -cp and --module-path
+ String jars = subJar.toString() + System.getProperty("path.separator") +
+ mainJar.toString();
+ output = TestCommon.createArchive( jars, appClasses,
+ "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+ "--module-path", moduleDir.toString(),
+ "-m", MAIN_MODULE);
+ TestCommon.checkDump(output);
+
+ // run with archive with the main class name specified before
+ // the module name with the -m option. Since the -m option was specified
+ // during dump time, the classes in the jar files after the -cp won't be
+ // archived. Therefore, the classes won't be loaded from the archive but
+ // will be loaded from the jar files.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", jars,
+ "--module-path", moduleDir.toString(),
+ MAIN_CLASS, "-m", MAIN_MODULE)
+ .assertNormalExit(out -> {
+ out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar")
+ .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+ });
+
+ // similar to the above case but without the main class name. The classes
+ // should be loaded from the archive.
+ TestCommon.run("-Xlog:class+load=trace",
+ "-cp", jars,
+ "--module-path", moduleDir.toString(),
+ "-m", MAIN_MODULE)
+ .assertNormalExit(
+ "[class,load] com.greetings.Main source: shared objects file",
+ "[class,load] org.astro.World source: shared objects file");
+
+ // create an archive with two modular jars in the --module-path
+ output = TestCommon.createArchive(
+ null, appClasses,
+ "--module-path", jars,
+ "-m", MAIN_MODULE);
+ TestCommon.checkDump(output);
+
+ // run with the above archive but with the modular jar containing the
+ // org.astro module in a different location.
+ // The org.astro.World class should be loaded from the jar.
+ // The Main class should still be loaded from the archive.
+ jars = destJar.toString() + System.getProperty("path.separator") +
+ mainJar.toString();
+ TestCommon.runWithModules(prefix,
+ null, // --upgrade-module-path
+ jars, // --module-path
+ MAIN_MODULE) // -m
+ .assertNormalExit(out -> {
+ out.shouldContain("[class,load] com.greetings.Main source: shared objects file")
+ .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/com/greetings/Main.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+package com.greetings;
+import org.astro.World;
+public class Main {
+ public static void main(String[] args) {
+ System.out.format("Greetings %s!\n", World.name());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/module-info.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+module com.greetings {
+ requires org.astro;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/com/hello/Main.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+package com.hello;
+import org.astro.World;
+public class Main {
+ public static void main(String[] args) {
+ System.out.format("Hello %s!\n", World.name());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/module-info.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+module com.hello {
+ requires org.astro;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.nomodule/com/nomodule/Main.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+package com.nomodule;
+import org.astro.World;
+public class Main {
+ public static void main(String[] args) {
+ System.out.format("Greetings %s!\n", World.name());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/com/norequires/Main.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+package com.norequires;
+import org.astro.World;
+public class Main {
+ public static void main(String[] args) {
+ System.out.format("Hello %s!\n", World.name());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/module-info.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+module com.norequires { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/com/simple/Main.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+package com.simple;
+
+import java.lang.reflect.Method;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Hello World!");
+ if (args.length > 0 && args[0].equals("with_add_opens")) {
+ Method method = ClassLoader.class.getDeclaredMethod("defineClass",
+ byte[].class, int.class, int.class);
+ method.setAccessible(true);
+ System.out.println("method.setAccessible succeeded!");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/module-info.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+module com.simple {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/module-info.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+module org.astro {
+ exports org.astro;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/org/astro/World.java Tue Apr 10 11:43:40 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ *
+ */
+
+package org.astro;
+public class World {
+ public static String name() {
+ return "world";
+ }
+}
--- a/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -25,9 +25,9 @@
import sun.hotspot.WhiteBox;
public class JvmtiApp {
- static Class forname() {
+ static Class forname(String cn) {
try {
- return Class.forName("Hello");
+ return Class.forName(cn);
} catch (Throwable t) {
return null;
}
@@ -40,9 +40,14 @@
// See ../JvmtiAddPath.java for how the classpaths are configured.
public static void main(String args[]) {
+ String cn = "Hello";
+ if (args.length >= 3) {
+ cn = args[args.length - 1];
+ }
+
if (args[0].equals("noadd")) {
- if (forname() != null) {
- failed("Hello class was loaded unexpectedly");
+ if (forname(cn) != null) {
+ failed(cn + " class was loaded unexpectedly");
}
// We use -verbose:class to verify that Extra.class IS loaded by AppCDS if
// the boot classpath HAS NOT been appended.
@@ -54,39 +59,41 @@
if (args[0].equals("bootonly")) {
wb.addToBootstrapClassLoaderSearch(args[1]);
- Class cls = forname();
+ Class cls = forname(cn);
if (cls == null) {
- failed("Cannot find Hello class");
+ failed("Cannot find " + cn + " class");
}
if (cls.getClassLoader() != null) {
failed("Hello class not loaded by boot classloader");
}
} else if (args[0].equals("apponly")) {
wb.addToSystemClassLoaderSearch(args[1]);
- Class cls = forname();
+ Class cls = forname(cn);
if (cls == null) {
- failed("Cannot find Hello class");
+ failed("Cannot find " + cn + " class");
}
if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) {
- failed("Hello class not loaded by app classloader");
+ failed(cn + " class not loaded by app classloader");
}
} else if (args[0].equals("noadd-appcds")) {
- Class cls = forname();
+ cn = (args.length == 1) ? "Hello" : args[1];
+ Class cls = forname(cn);
if (cls == null) {
- failed("Cannot find Hello class");
+ failed("Cannot find " + cn + " class");
}
if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) {
- failed("Hello class not loaded by app classloader");
+ failed(cn + " class not loaded by app classloader");
}
} else if (args[0].equals("appandboot")) {
wb.addToBootstrapClassLoaderSearch(args[1]);
wb.addToSystemClassLoaderSearch(args[2]);
- Class cls = forname();
+ cn = (args.length == 3) ? "Hello" : args[3];
+ Class cls = forname(cn);
if (cls == null) {
- failed("Cannot find Hello class");
+ failed("Cannot find " + cn + " class");
}
if (cls.getClassLoader() != null) {
- failed("Hello class not loaded by boot classloader");
+ failed(cn + " class not loaded by boot classloader");
}
} else {
failed("unknown option " + args[0]);
@@ -102,4 +109,4 @@
class ExtraClass {
static void doit() {}
-}
\ No newline at end of file
+}
--- a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java Tue Apr 10 11:43:40 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -50,7 +50,8 @@
"-Xlog:class+path=info",
"-version");
new OutputAnalyzer(pb.start())
- .shouldContain("ro space:"); // Make sure archive got created.
+ // --patch-module is not supported during CDS dumping
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
// Case 2: Test that directory in --patch-module is supported for CDS dumping
// Create a class file in the module java.base.
@@ -73,7 +74,8 @@
"-Xlog:class+path=info",
"-version");
new OutputAnalyzer(pb.start())
- .shouldContain("ro space:"); // Make sure archive got created.
+ // --patch-module is not supported during CDS dumping
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
// Case 3a: Test CDS dumping with jar file in --patch-module
BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
@@ -87,7 +89,8 @@
"-Xlog:class+path=info",
"PatchModuleMain", "javax.naming.spi.NamingManager");
new OutputAnalyzer(pb.start())
- .shouldContain("ro space:"); // Make sure archive got created.
+ // --patch-module is not supported during CDS dumping
+ .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
// Case 3b: Test CDS run with jar file in --patch-module
pb = ProcessTools.createJavaProcessBuilder(
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java Tue Apr 10 10:06:42 2018 -0400
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java Tue Apr 10 11:43:40 2018 -0700
@@ -117,6 +117,7 @@
private final boolean hasMappingFailure;
private final boolean hasAbnormalExit;
private final boolean hasNormalExit;
+ private final String CDS_DISABLED = "warning: CDS is disabled when the";
public Result(CDSOptions opts, OutputAnalyzer out) throws Exception {
options = opts;
@@ -126,7 +127,9 @@
hasNormalExit = (!hasMappingFailure) && (output.getExitValue() == 0);
if (hasNormalExit) {
- if ("on".equals(options.xShareMode) && output.getStderr().contains("java version")) {
+ if ("on".equals(options.xShareMode) &&
+ output.getStderr().contains("java version") &&
+ !output.getStderr().contains(CDS_DISABLED)) {
// "-showversion" is always passed in the command-line by the execXXX methods.
// During normal exit, we require that the VM to show that sharing was enabled.
output.shouldContain("sharing");
@@ -150,6 +153,26 @@
return this;
}
+ // When {--limit-modules, --patch-module, and/or --upgrade-module-path}
+ // are specified, CDS is silently disabled for both -Xshare:auto and -Xshare:on.
+ public Result assertSilentlyDisabledCDS(Checker checker) throws Exception {
+ if (hasMappingFailure) {
+ throw new RuntimeException("Unexpected mapping failure");
+ }
+ // this comes from a JVM warning message.
+ output.shouldContain(CDS_DISABLED);
+
+ checker.check(output);
+ return this;
+ }
+
+ public Result assertSilentlyDisabledCDS(int exitCode, String... matches) throws Exception {
+ return assertSilentlyDisabledCDS((out) -> {
+ out.shouldHaveExitValue(exitCode);
+ checkMatches(out, matches);
+ });
+ }
+
public Result ifNormalExit(Checker checker) throws Exception {
if (hasNormalExit) {
checker.check(output);