From f647d4d908a6760c116a3a762c4dc09e3ed95796 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Fri, 13 Dec 2024 19:19:42 +0000 Subject: [PATCH] 8345936: Call ClassLoader.getResourceAsByteArray only for multi-release jar Reviewed-by: iklam, dholmes --- src/hotspot/share/cds/filemap.cpp | 5 +++-- src/hotspot/share/cds/filemap.hpp | 4 +++- src/hotspot/share/classfile/classLoader.cpp | 10 ++++++---- src/hotspot/share/classfile/classLoader.hpp | 10 ++++++++-- src/hotspot/share/classfile/classLoaderExt.cpp | 5 +++++ 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 06298949e0a..c87081d9d14 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -347,6 +347,7 @@ void SharedClassPathEntry::init(bool is_modules_image, _type = jar_entry; _timestamp = st.st_mtime; _from_class_path_attr = cpe->from_class_path_attr(); + _is_multi_release = cpe->is_multi_release_jar(); } _filesize = st.st_size; _is_module_path = is_module_path; @@ -2680,7 +2681,7 @@ ClassPathEntry* FileMapInfo::get_classpath_entry_for_jvmti(int i, TRAPS) { jio_snprintf(msg, strlen(path) + 127, "error in finding JAR file %s", path); THROW_MSG_(vmSymbols::java_io_IOException(), msg, nullptr); } else { - ent = ClassLoader::create_class_path_entry(THREAD, path, &st, false, false); + ent = ClassLoader::create_class_path_entry(THREAD, path, &st, false, false, scpe->is_multi_release()); if (ent == nullptr) { char *msg = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(path) + 128); jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path); @@ -2715,7 +2716,7 @@ ClassFileStream* FileMapInfo::open_stream_for_jvmti(InstanceKlass* ik, Handle cl name->utf8_length()); ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); ClassFileStream* cfs; - if (class_loader() != nullptr && !cpe->is_modules_image()) { + if (class_loader() != nullptr && !cpe->is_modules_image() && cpe->is_multi_release_jar()) { cfs = get_stream_from_class_loader(class_loader, cpe, file_name, CHECK_NULL); } else { cfs = cpe->open_stream_for_loader(THREAD, file_name, loader_data); diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index cabb54769fe..6759b4a5020 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -64,6 +64,7 @@ class SharedClassPathEntry : public MetaspaceObj { u1 _type; bool _is_module_path; bool _from_class_path_attr; + bool _is_multi_release; time_t _timestamp; // jar timestamp, 0 if is directory, modules image or other int64_t _filesize; // jar/jimage file size, -1 if is directory, -2 if other Array* _name; @@ -71,7 +72,7 @@ class SharedClassPathEntry : public MetaspaceObj { public: SharedClassPathEntry() : _type(0), _is_module_path(false), - _from_class_path_attr(false), _timestamp(0), + _from_class_path_attr(false), _is_multi_release(false), _timestamp(0), _filesize(0), _name(nullptr), _manifest(nullptr) {} static int size() { static_assert(is_aligned(sizeof(SharedClassPathEntry), wordSize), "must be"); @@ -92,6 +93,7 @@ public: bool is_jar() const { return _type == jar_entry; } bool is_non_existent() const { return _type == non_existent_entry; } bool from_class_path_attr() { return _from_class_path_attr; } + bool is_multi_release() { return _is_multi_release; } time_t timestamp() const { return _timestamp; } const char* name() const; const char* manifest() const { diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index aac312c36a3..83d0e803ee1 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -303,10 +303,11 @@ ClassFileStream* ClassPathDirEntry::open_stream(JavaThread* current, const char* } ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, - bool is_boot_append, bool from_class_path_attr) : ClassPathEntry() { + bool is_boot_append, bool from_class_path_attr, bool multi_release) : ClassPathEntry() { _zip = zip; _zip_name = copy_path(zip_name); _from_class_path_attr = from_class_path_attr; + _multi_release = multi_release; } ClassPathZipEntry::~ClassPathZipEntry() { @@ -750,7 +751,8 @@ jzfile* ClassLoader::open_zip_file(const char* canonical_path, char** error_msg, ClassPathEntry* ClassLoader::create_class_path_entry(JavaThread* current, const char *path, const struct stat* st, bool is_boot_append, - bool from_class_path_attr) { + bool from_class_path_attr, + bool is_multi_release) { ClassPathEntry* new_entry = nullptr; if ((st->st_mode & S_IFMT) == S_IFREG) { ResourceMark rm(current); @@ -763,7 +765,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(JavaThread* current, char* error_msg = nullptr; jzfile* zip = open_zip_file(canonical_path, &error_msg, current); if (zip != nullptr && error_msg == nullptr) { - new_entry = new ClassPathZipEntry(zip, path, is_boot_append, from_class_path_attr); + new_entry = new ClassPathZipEntry(zip, path, is_boot_append, from_class_path_attr, is_multi_release); } else { #if INCLUDE_CDS ClassLoaderExt::set_has_non_jar_in_classpath(); @@ -796,7 +798,7 @@ ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bo jzfile* zip = open_zip_file(canonical_path, &error_msg, thread); if (zip != nullptr && error_msg == nullptr) { // create using canonical path - return new ClassPathZipEntry(zip, canonical_path, is_boot_append, false); + return new ClassPathZipEntry(zip, canonical_path, is_boot_append, false, false); } } } diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index d6780054904..8eb6593f07a 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -58,6 +58,8 @@ public: virtual bool is_modules_image() const { return false; } virtual bool is_jar_file() const { return false; } + virtual bool is_multi_release_jar() const { return false; } + virtual void set_multi_release_jar() {} // Is this entry created from the "Class-path" attribute from a JAR Manifest? virtual bool from_class_path_attr() const { return false; } virtual const char* name() const = 0; @@ -91,11 +93,14 @@ class ClassPathZipEntry: public ClassPathEntry { jzfile* _zip; // The zip archive const char* _zip_name; // Name of zip archive bool _from_class_path_attr; // From the "Class-path" attribute of a jar file + bool _multi_release; // multi-release jar public: bool is_jar_file() const { return true; } + bool is_multi_release_jar() const { return _multi_release; } + void set_multi_release_jar() { _multi_release = true; } bool from_class_path_attr() const { return _from_class_path_attr; } const char* name() const { return _zip_name; } - ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append, bool from_class_path_attr); + ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append, bool from_class_path_attr, bool multi_release); virtual ~ClassPathZipEntry(); u1* open_entry(JavaThread* current, const char* name, jint* filesize, bool nul_terminate); ClassFileStream* open_stream(JavaThread* current, const char* name); @@ -260,7 +265,8 @@ class ClassLoader: AllStatic { static ClassPathEntry* create_class_path_entry(JavaThread* current, const char *path, const struct stat* st, bool is_boot_append, - bool from_class_path_attr); + bool from_class_path_attr, + bool is_multi_release = false); // Canonicalizes path names, so strcmp will work properly. This is mainly // to avoid confusing the zip library diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp index b9e420899c2..f7b2906394d 100644 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ b/src/hotspot/share/classfile/classLoaderExt.cpp @@ -244,6 +244,10 @@ void ClassLoaderExt::process_jar_manifest(JavaThread* current, ClassPathEntry* e vm_exit_during_cds_dumping(err_msg("-Xshare:dump does not support Extension-List in JAR manifest: %s", entry->name())); } + if (strstr(manifest, "Multi-Release: true") != nullptr) { + entry->set_multi_release_jar(); + } + char* cp_attr = get_class_path_attr(entry->name(), manifest, manifest_size); if (cp_attr != nullptr && strlen(cp_attr) > 0) { @@ -299,6 +303,7 @@ void ClassLoaderExt::process_jar_manifest(JavaThread* current, ClassPathEntry* e file_start = file_end; } } + return; } void ClassLoaderExt::setup_search_paths(JavaThread* current) {