mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-25 05:45:11 +02:00
8075253: Multiversion JAR feature: CDS does not support MV-JARs
Handle "Multi-Release" jar during CDS dump time Reviewed-by: jiangli, iklam, minqi, redestad
This commit is contained in:
parent
b1e438f157
commit
c3fd09e417
3 changed files with 92 additions and 16 deletions
|
@ -226,11 +226,12 @@ ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() {
|
ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append) : ClassPathEntry() {
|
||||||
_zip = zip;
|
_zip = zip;
|
||||||
char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
|
char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
|
||||||
strcpy(copy, zip_name);
|
strcpy(copy, zip_name);
|
||||||
_zip_name = copy;
|
_zip_name = copy;
|
||||||
|
_is_boot_append = is_boot_append;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassPathZipEntry::~ClassPathZipEntry() {
|
ClassPathZipEntry::~ClassPathZipEntry() {
|
||||||
|
@ -274,12 +275,80 @@ u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_ter
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TRAPS) {
|
||||||
|
u1* buffer = NULL;
|
||||||
|
if (!_is_boot_append) {
|
||||||
|
assert(DumpSharedSpaces, "Should be called only for non-boot entries during dump time");
|
||||||
|
// We presume default is multi-release enabled
|
||||||
|
const char* multi_ver = Arguments::get_property("jdk.util.jar.enableMultiRelease");
|
||||||
|
const char* verstr = Arguments::get_property("jdk.util.jar.version");
|
||||||
|
bool is_multi_ver = (multi_ver == NULL ||
|
||||||
|
strcmp(multi_ver, "true") == 0 ||
|
||||||
|
strcmp(multi_ver, "force") == 0) &&
|
||||||
|
is_multiple_versioned(THREAD);
|
||||||
|
// command line version setting
|
||||||
|
int version = 0;
|
||||||
|
const int base_version = 8; // JDK8
|
||||||
|
int cur_ver = JDK_Version::current().major_version();
|
||||||
|
if (verstr != NULL) {
|
||||||
|
version = atoi(verstr);
|
||||||
|
if (version < base_version || version > cur_ver) {
|
||||||
|
is_multi_ver = false;
|
||||||
|
// print out warning, do not use assertion here since it will continue to look
|
||||||
|
// for proper version.
|
||||||
|
warning("JDK%d is not supported in multiple version jars", version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_multi_ver) {
|
||||||
|
int n;
|
||||||
|
char entry_name[JVM_MAXPATHLEN];
|
||||||
|
if (version > 0) {
|
||||||
|
n = jio_snprintf(entry_name, sizeof(entry_name), "META-INF/versions/%d/%s", version, name);
|
||||||
|
entry_name[n] = '\0';
|
||||||
|
buffer = open_entry((const char*)entry_name, filesize, false, CHECK_NULL);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
warning("Could not find %s in %s, try to find highest version instead", entry_name, _zip_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buffer == NULL) {
|
||||||
|
for (int i = cur_ver; i >= base_version; i--) {
|
||||||
|
n = jio_snprintf(entry_name, sizeof(entry_name), "META-INF/versions/%d/%s", i, name);
|
||||||
|
entry_name[n] = '\0';
|
||||||
|
buffer = open_entry((const char*)entry_name, filesize, false, CHECK_NULL);
|
||||||
|
if (buffer != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassPathZipEntry::is_multiple_versioned(TRAPS) {
|
||||||
|
assert(DumpSharedSpaces, "called only at dump time");
|
||||||
|
jint size;
|
||||||
|
char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, false, CHECK_false);
|
||||||
|
if (buffer != NULL) {
|
||||||
|
if (strstr(buffer, "Multi-Release: true") != NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // INCLUDE_CDS
|
||||||
|
|
||||||
ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
|
ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
|
||||||
jint filesize;
|
jint filesize;
|
||||||
const u1* buffer = open_entry(name, &filesize, false, CHECK_NULL);
|
u1* buffer = open_versioned_entry(name, &filesize, CHECK_NULL);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
buffer = open_entry(name, &filesize, false, CHECK_NULL);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
|
ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
|
||||||
}
|
}
|
||||||
|
@ -558,7 +627,7 @@ void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_searc
|
||||||
char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
|
char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
|
||||||
strncpy(path, &class_path[start], end - start);
|
strncpy(path, &class_path[start], end - start);
|
||||||
path[end - start] = '\0';
|
path[end - start] = '\0';
|
||||||
update_class_path_entry_list(path, false, mark_append_entry, false);
|
update_class_path_entry_list(path, false, mark_append_entry, false, bootstrap_search);
|
||||||
|
|
||||||
// Check on the state of the boot loader's append path
|
// Check on the state of the boot loader's append path
|
||||||
if (mark_append_entry && (_first_append_entry == NULL)) {
|
if (mark_append_entry && (_first_append_entry == NULL)) {
|
||||||
|
@ -582,7 +651,8 @@ void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_searc
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
|
ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
|
||||||
bool throw_exception, TRAPS) {
|
bool throw_exception,
|
||||||
|
bool is_boot_append, TRAPS) {
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
ClassPathEntry* new_entry = NULL;
|
ClassPathEntry* new_entry = NULL;
|
||||||
if ((st->st_mode & S_IFREG) == S_IFREG) {
|
if ((st->st_mode & S_IFREG) == S_IFREG) {
|
||||||
|
@ -611,7 +681,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str
|
||||||
zip = (*ZipOpen)(canonical_path, &error_msg);
|
zip = (*ZipOpen)(canonical_path, &error_msg);
|
||||||
}
|
}
|
||||||
if (zip != NULL && error_msg == NULL) {
|
if (zip != NULL && error_msg == NULL) {
|
||||||
new_entry = new ClassPathZipEntry(zip, path);
|
new_entry = new ClassPathZipEntry(zip, path, is_boot_append);
|
||||||
} else {
|
} else {
|
||||||
ResourceMark rm(thread);
|
ResourceMark rm(thread);
|
||||||
char *msg;
|
char *msg;
|
||||||
|
@ -644,7 +714,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str
|
||||||
|
|
||||||
// Create a class path zip entry for a given path (return NULL if not found
|
// Create a class path zip entry for a given path (return NULL if not found
|
||||||
// or zip/JAR file cannot be opened)
|
// or zip/JAR file cannot be opened)
|
||||||
ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) {
|
ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bool is_boot_append) {
|
||||||
// check for a regular file
|
// check for a regular file
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (os::stat(path, &st) == 0) {
|
if (os::stat(path, &st) == 0) {
|
||||||
|
@ -662,7 +732,7 @@ ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) {
|
||||||
}
|
}
|
||||||
if (zip != NULL && error_msg == NULL) {
|
if (zip != NULL && error_msg == NULL) {
|
||||||
// create using canonical path
|
// create using canonical path
|
||||||
return new ClassPathZipEntry(zip, canonical_path);
|
return new ClassPathZipEntry(zip, canonical_path, is_boot_append);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -720,11 +790,11 @@ void ClassLoader::prepend_to_list(ClassPathEntry *new_entry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoader::add_to_list(const char *apath) {
|
void ClassLoader::add_to_list(const char *apath) {
|
||||||
update_class_path_entry_list((char*)apath, false, false, false);
|
update_class_path_entry_list((char*)apath, false, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoader::prepend_to_list(const char *apath) {
|
void ClassLoader::prepend_to_list(const char *apath) {
|
||||||
update_class_path_entry_list((char*)apath, false, false, true);
|
update_class_path_entry_list((char*)apath, false, false, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true IFF the file/dir exists and the entry was successfully created.
|
// Returns true IFF the file/dir exists and the entry was successfully created.
|
||||||
|
@ -732,13 +802,14 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
|
||||||
bool check_for_duplicates,
|
bool check_for_duplicates,
|
||||||
bool mark_append_entry,
|
bool mark_append_entry,
|
||||||
bool prepend_entry,
|
bool prepend_entry,
|
||||||
|
bool is_boot_append,
|
||||||
bool throw_exception) {
|
bool throw_exception) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (os::stat(path, &st) == 0) {
|
if (os::stat(path, &st) == 0) {
|
||||||
// File or directory found
|
// File or directory found
|
||||||
ClassPathEntry* new_entry = NULL;
|
ClassPathEntry* new_entry = NULL;
|
||||||
Thread* THREAD = Thread::current();
|
Thread* THREAD = Thread::current();
|
||||||
new_entry = create_class_path_entry(path, &st, throw_exception, CHECK_(false));
|
new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, CHECK_(false));
|
||||||
if (new_entry == NULL) {
|
if (new_entry == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,16 +104,19 @@ class ClassPathZipEntry: public ClassPathEntry {
|
||||||
private:
|
private:
|
||||||
jzfile* _zip; // The zip archive
|
jzfile* _zip; // The zip archive
|
||||||
const char* _zip_name; // Name of zip archive
|
const char* _zip_name; // Name of zip archive
|
||||||
|
bool _is_boot_append; // entry coming from -Xbootclasspath/a
|
||||||
public:
|
public:
|
||||||
bool is_jrt() { return false; }
|
bool is_jrt() { return false; }
|
||||||
bool is_jar_file() const { return true; }
|
bool is_jar_file() const { return true; }
|
||||||
const char* name() const { return _zip_name; }
|
const char* name() const { return _zip_name; }
|
||||||
JImageFile* jimage() const { return NULL; }
|
JImageFile* jimage() const { return NULL; }
|
||||||
ClassPathZipEntry(jzfile* zip, const char* zip_name);
|
ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append);
|
||||||
~ClassPathZipEntry();
|
~ClassPathZipEntry();
|
||||||
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
||||||
|
u1* open_versioned_entry(const char* name, jint* filesize, TRAPS) NOT_CDS_RETURN_(NULL);
|
||||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
void contents_do(void f(const char* name, void* context), void* context);
|
void contents_do(void f(const char* name, void* context), void* context);
|
||||||
|
bool is_multiple_versioned(TRAPS) NOT_CDS_RETURN_(false);
|
||||||
// Debugging
|
// Debugging
|
||||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||||
};
|
};
|
||||||
|
@ -223,7 +226,8 @@ class ClassLoader: AllStatic {
|
||||||
static void load_zip_library();
|
static void load_zip_library();
|
||||||
static void load_jimage_library();
|
static void load_jimage_library();
|
||||||
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
|
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
|
||||||
bool throw_exception, TRAPS);
|
bool throw_exception,
|
||||||
|
bool is_boot_append, TRAPS);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -249,6 +253,7 @@ class ClassLoader: AllStatic {
|
||||||
bool check_for_duplicates,
|
bool check_for_duplicates,
|
||||||
bool mark_append_entry,
|
bool mark_append_entry,
|
||||||
bool prepend_entry,
|
bool prepend_entry,
|
||||||
|
bool is_boot_append,
|
||||||
bool throw_exception=true);
|
bool throw_exception=true);
|
||||||
static void print_bootclasspath();
|
static void print_bootclasspath();
|
||||||
|
|
||||||
|
@ -394,7 +399,7 @@ class ClassLoader: AllStatic {
|
||||||
static void prepend_to_list(ClassPathEntry* new_entry);
|
static void prepend_to_list(ClassPathEntry* new_entry);
|
||||||
|
|
||||||
// creates a class path zip entry (returns NULL if JAR file cannot be opened)
|
// creates a class path zip entry (returns NULL if JAR file cannot be opened)
|
||||||
static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
|
static ClassPathZipEntry* create_class_path_zip_entry(const char *apath, bool is_boot_append);
|
||||||
|
|
||||||
// add a path to class path list
|
// add a path to class path list
|
||||||
static void add_to_list(const char* apath);
|
static void add_to_list(const char* apath);
|
||||||
|
|
|
@ -476,7 +476,7 @@ JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) {
|
||||||
// terminating the VM so we check one more time.
|
// terminating the VM so we check one more time.
|
||||||
|
|
||||||
// create the zip entry
|
// create the zip entry
|
||||||
ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
|
ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment, true);
|
||||||
if (zip_entry == NULL) {
|
if (zip_entry == NULL) {
|
||||||
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
@ -520,7 +520,7 @@ JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) {
|
||||||
|
|
||||||
// create the zip entry (which will open the zip file and hence
|
// create the zip entry (which will open the zip file and hence
|
||||||
// check that the segment is indeed a zip file).
|
// check that the segment is indeed a zip file).
|
||||||
ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
|
ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment, false);
|
||||||
if (zip_entry == NULL) {
|
if (zip_entry == NULL) {
|
||||||
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue