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
This commit is contained in:
Calvin Cheung 2018-04-10 11:43:40 -07:00
parent d187884156
commit 4ef7c919a2
55 changed files with 2009 additions and 349 deletions

View file

@ -148,6 +148,8 @@ ClassPathEntry* ClassLoader::_last_append_entry = NULL;
#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 @@ void ClassLoader::setup_app_search_path(const char *class_path) {
}
}
#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 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
}
#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 @@ static char* skip_uri_protocol(char* source) {
// 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 @@ void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream
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 @@ void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream
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;
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);
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 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:"))) {
// 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;
}
}
}
if (classpath_index < 0) {
// Shared classpath entry table only contains boot class path and -cp path.
}
// 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;
}
}
}
// No path entry found for this class. Must be a shared class loaded by the
// user defined classloader.
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 @@ void ClassLoader::initialize_shared_path() {
_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() {

View file

@ -238,12 +238,18 @@ class ClassLoader: AllStatic {
CDS_ONLY(static ClassPathEntry* _app_classpath_entries;)
CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;)
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 @@ class ClassLoader: AllStatic {
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 @@ class ClassLoader: AllStatic {
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 @@ class ClassLoader: AllStatic {
// 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);

View file

@ -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::setup_app_search_path() {
}
}
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_search_paths() {
}
}
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,

View file

@ -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 @@ public:
_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 @@ public:
~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 @@ private:
#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 @@ public:
}
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 @@ public:
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() {

View file

@ -84,7 +84,7 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook(
}
} 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 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
#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

View file

@ -85,7 +85,7 @@ static const char* get_module_version(jstring version) {
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);

View file

@ -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 @@ public:
// 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

View file

@ -93,6 +93,9 @@ void SharedPathsMiscInfoExt::print_path(outputStream* out, int type, const char*
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::update_shared_classpath(ClassPathEntry *cpe, SharedClassPa
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 @@ void SharedClassUtil::read_extra_data(const char* filename, TRAPS) {
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 @@ void FileMapHeaderExt::populate(FileMapInfo* mapinfo, size_t alignment) {
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;

View file

@ -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,7 +34,8 @@
class FileMapHeaderExt: public FileMapInfo::FileMapHeader {
public:
jshort _app_paths_start_index; // Index of first app classpath entry
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
@ -56,12 +57,14 @@ private:
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);
}
}

View file

@ -1217,7 +1217,7 @@ bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
}
}
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");

View file

@ -92,7 +92,7 @@ Handle SystemDictionaryShared::get_shared_jar_manifest(int shared_path_index, TR
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 SystemDictionaryShared::get_shared_jar_url(int shared_path_index, TRAPS)
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 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
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 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
// 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 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
}
// 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 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK
// 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 @@ bool SystemDictionaryShared::is_shared_class_visible_for_classloader(
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 @@ bool SystemDictionaryShared::is_shared_class_visible_for_classloader(
// 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 @@ bool SystemDictionaryShared::is_shared_class_visible_for_classloader(
// 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 @@ bool SystemDictionaryShared::is_shared_class_visible_for_classloader(
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");)
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");
}
}
}
}

View file

@ -96,7 +96,7 @@ void FileMapInfo::fail_continue(const char *msg, ...) {
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 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment
_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 @@ void SharedClassPathEntry::init(const char* name, TRAPS) {
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 @@ void SharedClassPathEntry::metaspace_pointers_do(MetaspaceClosure* it) {
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 @@ void FileMapInfo::allocate_classpath_entry_table() {
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 @@ void FileMapInfo::allocate_classpath_entry_table() {
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 @@ void FileMapInfo::allocate_classpath_entry_table() {
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++;
}
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;
int count = _header->_classpath_entry_table_size;
_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;
_classpath_entry_table = _header->_classpath_entry_table;
_classpath_entry_size = _header->_classpath_entry_size;
_classpath_entry_table_size = _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;
int count = _shared_path_table_size;
for (int i=0; i<count; i++) {
if (shared_classpath(i)->validate()) {
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::assert_mark(bool check) {
}
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 @@ bool FileMapInfo::_validating_classpath_entry_table = false;
// 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 @@ int FileMapInfo::FileMapHeader::compute_crc() {
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.");

View file

@ -53,7 +53,7 @@ protected:
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 @@ private:
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 @@ public:
// 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 @@ public:
// 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 @@ public:
// 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:

View file

@ -1619,7 +1619,6 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
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 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
(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().

View file

@ -150,7 +150,7 @@ class Klass : public Metadata {
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.

View file

@ -1446,35 +1446,23 @@ bool Arguments::add_property(const char* prop, PropertyWriteable writeable, Prop
}
#if INCLUDE_CDS
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",
const char* unsupported_properties[] = { "jdk.module.limitmods",
"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
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");
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]);
}
}
}
sp = sp->next();
@ -1485,6 +1473,20 @@ void Arguments::check_unsupported_dumping_properties() {
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 @@ jint Arguments::finalize_vm_init_args(bool patch_mod_javabase) {
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

View file

@ -703,6 +703,8 @@ class Arguments : AllStatic {
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);
};

View file

@ -3891,6 +3891,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
// 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);

View file

@ -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 class JarBuilder {
}
}
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 @@ public class JarBuilder {
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");

View file

@ -200,13 +200,18 @@ public class TestCommon extends CDSTestUtils {
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 @@ public class TestCommon extends CDSTestUtils {
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 @@ public class TestCommon extends CDSTestUtils {
"-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);
}

View file

@ -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 @@ import jdk.test.lib.process.OutputAnalyzer;
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 @@ public class CheckUnsupportedDumpingOptions {
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);
}
}
}
}
}

View file

@ -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 @@ public class JigsawOptionsCombo {
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 @@ public class JigsawOptionsCombo {
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 @@ public class JigsawOptionsCombo {
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 @@ public class JigsawOptionsCombo {
String runTimeArgs;
String runTimeExpectedOutput;
int runTimeExpectedExitValue;
boolean sharingOn;
private String appJar = TestCommon.getTestJar("hello.jar");
private String appClasses[] = {"Hello"};
@ -152,7 +151,8 @@ public class JigsawOptionsCombo {
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 @@ public class JigsawOptionsCombo {
this.runTimeArgs = runTimeArgs;
this.runTimeExpectedOutput = runTimeExpectedOutput;
this.runTimeExpectedExitValue = runTimeExpectedExitValue;
this.sharingOn = sharingOn;
}
@ -183,7 +184,13 @@ public class JigsawOptionsCombo {
OutputAnalyzer execOutput = TestCommon.exec(appJar, getRunOptions());
if (runTimeExpectedExitValue == 0) {
if (sharingOn) {
TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World");
} else {
execOutput.shouldHaveExitValue(0)
.shouldContain(runTimeExpectedOutput)
.shouldContain("Hello World");
}
} else {
execOutput.shouldMatch(dumpTimeExpectedOutput);
execOutput.shouldHaveExitValue(dumpTimeExpectedExitValue);

View file

@ -86,7 +86,8 @@ public class AppClassInCP {
"--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 @@ public class AppClassInCP {
"--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!");
}
}

View file

@ -70,7 +70,8 @@ public class CustomPackage {
"-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 @@ public class CustomPackage {
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.myspi.NamingManager")
.assertNormalExit("I pass!");
.assertSilentlyDisabledCDS(0, "I pass!");
}
}

View file

@ -62,64 +62,24 @@ public class MismatchedPatchModule {
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");
output.shouldHaveExitValue(1)
.shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
// 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!"));
// 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"),
"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,
"-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",
@ -127,6 +87,6 @@ public class MismatchedPatchModule {
"--patch-module=java.naming2=" + moduleJar,
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager")
.assertNormalExit("I pass!");
.assertSilentlyDisabledCDS(0, "I pass!");
}
}

View file

@ -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 @@ public class PatchDir {
"--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);
}
}

View file

@ -62,7 +62,8 @@ public class PatchJavaBase {
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",

View file

@ -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 @@ public class Simple {
"-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 @@ public class Simple {
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager")
.assertNormalExit("I pass!");
.assertSilentlyDisabledCDS(0, "I pass!");
}
}

View file

@ -88,7 +88,8 @@ public class SubClassOfPatchedClass {
"--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 @@ public class SubClassOfPatchedClass {
"--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!");
}
}

View file

@ -87,7 +87,8 @@ public class TwoJars {
"-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 @@ public class TwoJars {
"-Xlog:class+load",
"-Xlog:class+path=info",
"PatchMain", "javax.naming.spi.NamingManager")
.assertNormalExit("I pass");
.assertSilentlyDisabledCDS(0, "I pass!");
}
}

View file

@ -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 @@ public class BootAppendTests {
// 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 class BootAppendTests {
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");
});
}
}

View file

@ -89,13 +89,15 @@ public class EmptyClassInBootClassPath {
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);
}
}

View file

@ -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,13 +65,24 @@ public class LimitModsHelper {
// Make sure we got the expected defining ClassLoader
testLoader(clazz, expectedLoaders[i]);
// Make sure the class is in the shared space
// 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;
}
}

View file

@ -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 @@ public class LimitModsTests {
}
}
}
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;
}
}

View file

@ -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");
});
}
}

View file

@ -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!");
}
}

View file

@ -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");
});
}
}

View file

@ -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");
}
}

View file

@ -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);
}
}

View file

@ -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:");
}
}

View file

@ -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");
});
}
}

View file

@ -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());
}
}

View file

@ -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;
}

View file

@ -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());
}
}

View file

@ -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;
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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 { }

View file

@ -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!");
}
}
}

View file

@ -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 {
}

View file

@ -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;
}

View file

@ -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";
}
}

View file

@ -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 @@ public class JvmtiApp {
// 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 @@ public class JvmtiApp {
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]);

View file

@ -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 @@ public class PatchModuleCDS {
"-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 @@ public class PatchModuleCDS {
"-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 @@ public class PatchModuleCDS {
"-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(

View file

@ -117,6 +117,7 @@ public class CDSTestUtils {
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 @@ public class CDSTestUtils {
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 @@ public class CDSTestUtils {
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);