8263421: Module image file is opened twice during VM startup

Reviewed-by: iklam, dholmes
This commit is contained in:
Harold Seigel 2021-04-27 13:31:55 +00:00
parent fbfd4ea3ce
commit dc323a9334
2 changed files with 43 additions and 52 deletions

View file

@ -105,10 +105,11 @@ int ClassLoader::_libzip_loaded = 0;
static JImageOpen_t JImageOpen = NULL; static JImageOpen_t JImageOpen = NULL;
static JImageClose_t JImageClose = NULL; static JImageClose_t JImageClose = NULL;
static JImagePackageToModule_t JImagePackageToModule = NULL;
static JImageFindResource_t JImageFindResource = NULL; static JImageFindResource_t JImageFindResource = NULL;
static JImageGetResource_t JImageGetResource = NULL; static JImageGetResource_t JImageGetResource = NULL;
static JImageResourceIterator_t JImageResourceIterator = NULL;
// JimageFile pointer, or null if exploded JDK build.
static JImageFile* JImage_file = NULL;
// Globals // Globals
@ -343,16 +344,26 @@ void ClassPathZipEntry::contents_do(void f(const char* name, void* context), voi
DEBUG_ONLY(ClassPathImageEntry* ClassPathImageEntry::_singleton = NULL;) DEBUG_ONLY(ClassPathImageEntry* ClassPathImageEntry::_singleton = NULL;)
JImageFile* ClassPathImageEntry::jimage() const {
return JImage_file;
}
JImageFile* ClassPathImageEntry::jimage_non_null() const {
assert(ClassLoader::has_jrt_entry(), "must be");
assert(jimage() != NULL, "should have been opened by ClassLoader::lookup_vm_options "
"and remained throughout normal JVM lifetime");
return jimage();
}
void ClassPathImageEntry::close_jimage() { void ClassPathImageEntry::close_jimage() {
if (_jimage != NULL) { if (jimage() != NULL) {
(*JImageClose)(_jimage); (*JImageClose)(jimage());
_jimage = NULL; JImage_file = NULL;
} }
} }
ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) : ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) :
ClassPathEntry(), ClassPathEntry() {
_jimage(jimage) {
guarantee(jimage != NULL, "jimage file is null"); guarantee(jimage != NULL, "jimage file is null");
guarantee(name != NULL, "jimage file name is null"); guarantee(name != NULL, "jimage file name is null");
assert(_singleton == NULL, "VM supports only one jimage"); assert(_singleton == NULL, "VM supports only one jimage");
@ -361,18 +372,6 @@ ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) :
_name = copy_path(name); _name = copy_path(name);
} }
ClassPathImageEntry::~ClassPathImageEntry() {
assert(_singleton == this, "must be");
DEBUG_ONLY(_singleton = NULL);
FREE_C_HEAP_ARRAY(const char, _name);
if (_jimage != NULL) {
(*JImageClose)(_jimage);
_jimage = NULL;
}
}
ClassFileStream* ClassPathImageEntry::open_stream(Thread* current, const char* name) { ClassFileStream* ClassPathImageEntry::open_stream(Thread* current, const char* name) {
return open_stream_for_loader(current, name, ClassLoaderData::the_null_class_loader_data()); return open_stream_for_loader(current, name, ClassLoaderData::the_null_class_loader_data());
} }
@ -386,7 +385,7 @@ ClassFileStream* ClassPathImageEntry::open_stream(Thread* current, const char* n
// //
ClassFileStream* ClassPathImageEntry::open_stream_for_loader(Thread* current, const char* name, ClassLoaderData* loader_data) { ClassFileStream* ClassPathImageEntry::open_stream_for_loader(Thread* current, const char* name, ClassLoaderData* loader_data) {
jlong size; jlong size;
JImageLocationRef location = (*JImageFindResource)(_jimage, "", get_jimage_version_string(), name, &size); JImageLocationRef location = (*JImageFindResource)(jimage_non_null(), "", get_jimage_version_string(), name, &size);
if (location == 0) { if (location == 0) {
TempNewSymbol class_name = SymbolTable::new_symbol(name); TempNewSymbol class_name = SymbolTable::new_symbol(name);
@ -394,7 +393,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(Thread* current, co
if (pkg_name != NULL) { if (pkg_name != NULL) {
if (!Universe::is_module_initialized()) { if (!Universe::is_module_initialized()) {
location = (*JImageFindResource)(_jimage, JAVA_BASE_NAME, get_jimage_version_string(), name, &size); location = (*JImageFindResource)(jimage_non_null(), JAVA_BASE_NAME, get_jimage_version_string(), name, &size);
} else { } else {
PackageEntry* package_entry = ClassLoader::get_package_entry(pkg_name, loader_data); PackageEntry* package_entry = ClassLoader::get_package_entry(pkg_name, loader_data);
if (package_entry != NULL) { if (package_entry != NULL) {
@ -405,7 +404,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(Thread* current, co
assert(module->is_named(), "Boot classLoader package is in unnamed module"); assert(module->is_named(), "Boot classLoader package is in unnamed module");
const char* module_name = module->name()->as_C_string(); const char* module_name = module->name()->as_C_string();
if (module_name != NULL) { if (module_name != NULL) {
location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size); location = (*JImageFindResource)(jimage_non_null(), module_name, get_jimage_version_string(), name, &size);
} }
} }
} }
@ -416,7 +415,7 @@ ClassFileStream* ClassPathImageEntry::open_stream_for_loader(Thread* current, co
ClassLoader::perf_sys_classfile_bytes_read()->inc(size); ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
} }
char* data = NEW_RESOURCE_ARRAY(char, size); char* data = NEW_RESOURCE_ARRAY(char, size);
(*JImageGetResource)(_jimage, location, data, size); (*JImageGetResource)(jimage_non_null(), location, data, size);
// Resource allocated // Resource allocated
assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be"); assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be");
return new ClassFileStream((u1*)data, return new ClassFileStream((u1*)data,
@ -649,14 +648,17 @@ void ClassLoader::setup_bootstrap_search_path_impl(Thread* current, const char *
struct stat st; struct stat st;
if (os::stat(path, &st) == 0) { if (os::stat(path, &st) == 0) {
// Directory found // Directory found
ClassPathEntry* new_entry = create_class_path_entry(current, path, &st, false, false); if (JImage_file != NULL) {
assert(Arguments::has_jimage(), "sanity check");
const char* canonical_path = get_canonical_path(path, current);
assert(canonical_path != NULL, "canonical_path issue");
// Check for a jimage _jrt_entry = new ClassPathImageEntry(JImage_file, canonical_path);
if (Arguments::has_jimage()) { assert(_jrt_entry != NULL && _jrt_entry->is_modules_image(), "No java runtime image present");
assert(_jrt_entry == NULL, "should not setup bootstrap class search path twice");
_jrt_entry = new_entry;
assert(new_entry != NULL && new_entry->is_modules_image(), "No java runtime image present");
assert(_jrt_entry->jimage() != NULL, "No java runtime image"); assert(_jrt_entry->jimage() != NULL, "No java runtime image");
} else {
// It's an exploded build.
ClassPathEntry* new_entry = create_class_path_entry(current, path, &st, false, false);
} }
} else { } else {
// If path does not exist, exit // If path does not exist, exit
@ -724,24 +726,18 @@ ClassPathEntry* ClassLoader::create_class_path_entry(Thread* current,
ClassPathEntry* new_entry = NULL; ClassPathEntry* new_entry = NULL;
if ((st->st_mode & S_IFMT) == S_IFREG) { if ((st->st_mode & S_IFMT) == S_IFREG) {
ResourceMark rm(thread); ResourceMark rm(thread);
// Regular file, should be a zip or jimage file // Regular file, should be a zip file
// Canonicalized filename // Canonicalized filename
const char* canonical_path = get_canonical_path(path, thread); const char* canonical_path = get_canonical_path(path, thread);
if (canonical_path == NULL) { if (canonical_path == NULL) {
return NULL; return NULL;
} }
jint error; char* error_msg = NULL;
JImageFile* jimage =(*JImageOpen)(canonical_path, &error); jzfile* zip = open_zip_file(canonical_path, &error_msg, thread);
if (jimage != NULL) { if (zip != NULL && error_msg == NULL) {
new_entry = new ClassPathImageEntry(jimage, canonical_path); new_entry = new ClassPathZipEntry(zip, path, is_boot_append, from_class_path_attr);
} else { } else {
char* error_msg = NULL; return NULL;
jzfile* zip = open_zip_file(canonical_path, &error_msg, thread);
if (zip != NULL && error_msg == NULL) {
new_entry = new ClassPathZipEntry(zip, path, is_boot_append, from_class_path_attr);
} else {
return NULL;
}
} }
log_info(class, path)("opened: %s", path); log_info(class, path)("opened: %s", path);
log_info(class, load)("opened: %s", path); log_info(class, load)("opened: %s", path);
@ -968,10 +964,8 @@ void ClassLoader::load_jimage_library() {
JImageOpen = CAST_TO_FN_PTR(JImageOpen_t, dll_lookup(handle, "JIMAGE_Open", path)); JImageOpen = CAST_TO_FN_PTR(JImageOpen_t, dll_lookup(handle, "JIMAGE_Open", path));
JImageClose = CAST_TO_FN_PTR(JImageClose_t, dll_lookup(handle, "JIMAGE_Close", path)); JImageClose = CAST_TO_FN_PTR(JImageClose_t, dll_lookup(handle, "JIMAGE_Close", path));
JImagePackageToModule = CAST_TO_FN_PTR(JImagePackageToModule_t, dll_lookup(handle, "JIMAGE_PackageToModule", path));
JImageFindResource = CAST_TO_FN_PTR(JImageFindResource_t, dll_lookup(handle, "JIMAGE_FindResource", path)); JImageFindResource = CAST_TO_FN_PTR(JImageFindResource_t, dll_lookup(handle, "JIMAGE_FindResource", path));
JImageGetResource = CAST_TO_FN_PTR(JImageGetResource_t, dll_lookup(handle, "JIMAGE_GetResource", path)); JImageGetResource = CAST_TO_FN_PTR(JImageGetResource_t, dll_lookup(handle, "JIMAGE_GetResource", path));
JImageResourceIterator = CAST_TO_FN_PTR(JImageResourceIterator_t, dll_lookup(handle, "JIMAGE_ResourceIterator", path));
} }
int ClassLoader::crc32(int crc, const char* buf, int len) { int ClassLoader::crc32(int crc, const char* buf, int len) {
@ -1429,15 +1423,13 @@ char* ClassLoader::lookup_vm_options() {
load_jimage_library(); load_jimage_library();
jio_snprintf(modules_path, JVM_MAXPATHLEN, "%s%slib%smodules", Arguments::get_java_home(), fileSep, fileSep); jio_snprintf(modules_path, JVM_MAXPATHLEN, "%s%slib%smodules", Arguments::get_java_home(), fileSep, fileSep);
JImageFile* jimage =(*JImageOpen)(modules_path, &error); JImage_file =(*JImageOpen)(modules_path, &error);
if (jimage == NULL) { if (JImage_file == NULL) {
return NULL; return NULL;
} }
const char *jimage_version = get_jimage_version_string(); const char *jimage_version = get_jimage_version_string();
char *options = lookup_vm_resource(jimage, jimage_version, "jdk/internal/vm/options"); char *options = lookup_vm_resource(JImage_file, jimage_version, "jdk/internal/vm/options");
(*JImageClose)(jimage);
return options; return options;
} }

View file

@ -117,17 +117,16 @@ class ClassPathZipEntry: public ClassPathEntry {
// For java image files // For java image files
class ClassPathImageEntry: public ClassPathEntry { class ClassPathImageEntry: public ClassPathEntry {
private: private:
JImageFile* _jimage;
const char* _name; const char* _name;
DEBUG_ONLY(static ClassPathImageEntry* _singleton;) DEBUG_ONLY(static ClassPathImageEntry* _singleton;)
public: public:
bool is_modules_image() const; bool is_modules_image() const;
bool is_open() const { return _jimage != NULL; }
const char* name() const { return _name == NULL ? "" : _name; } const char* name() const { return _name == NULL ? "" : _name; }
JImageFile* jimage() const { return _jimage; } JImageFile* jimage() const;
JImageFile* jimage_non_null() const;
void close_jimage(); void close_jimage();
ClassPathImageEntry(JImageFile* jimage, const char* name); ClassPathImageEntry(JImageFile* jimage, const char* name);
virtual ~ClassPathImageEntry(); virtual ~ClassPathImageEntry() { ShouldNotReachHere(); }
ClassFileStream* open_stream(Thread* current, const char* name); ClassFileStream* open_stream(Thread* current, const char* name);
ClassFileStream* open_stream_for_loader(Thread* current, const char* name, ClassLoaderData* loader_data); ClassFileStream* open_stream_for_loader(Thread* current, const char* name, ClassLoaderData* loader_data);
}; };