src/share/vm/classfile/classLoader.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/classfile/classLoader.cpp

src/share/vm/classfile/classLoader.cpp

Print this page

        

*** 83,102 **** --- 83,104 ---- typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg); typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); + typedef void (JNICALL *FreeEntry_t)(jzfile *zip, jzentry *entry); static ZipOpen_t ZipOpen = NULL; static ZipClose_t ZipClose = NULL; static FindEntry_t FindEntry = NULL; static ReadEntry_t ReadEntry = NULL; static ReadMappedEntry_t ReadMappedEntry = NULL; static GetNextEntry_t GetNextEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL; static ZipInflateFully_t ZipInflateFully = NULL; static Crc32_t Crc32 = NULL; + static FreeEntry_t FreeEntry = NULL; // Entry points for jimage.dll for loading jimage file entries static JImageOpen_t JImageOpen = NULL; static JImageClose_t JImageClose = NULL;
*** 148,157 **** --- 150,160 ---- int ClassLoader::_num_entries = 0; #if INCLUDE_CDS GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL; GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL; SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL; + int ClassLoader::_num_patch_mod_prefixes = 0; #endif // helper routines bool string_starts_with(const char* str, const char* str_to_find) { size_t str_len = strlen(str);
*** 317,326 **** --- 320,343 ---- (*ZipClose)(_zip); } FREE_C_HEAP_ARRAY(char, _zip_name); } + bool ClassPathZipEntry::stream_exists(const char* name) { + // enable call to C land + JavaThread* thread = JavaThread::current(); + ThreadToNativeFromVM ttn(thread); + // check whether zip archive contains name + jint name_len, filesize; + jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len); + if (entry != NULL) { + (*FreeEntry)(_zip, entry); + return true; + } + return false; + } + u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { // enable call to C land JavaThread* thread = JavaThread::current(); ThreadToNativeFromVM ttn(thread); // check whether zip archive contains name
*** 638,648 **** exit_with_path_failure("Cannot have empty path in archived classpaths", NULL); } struct stat st; if (os::stat(path, &st) == 0) { ! if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory if (!os::dir_is_empty(path)) { tty->print_cr("Error: non-empty directory '%s'", path); exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL); } } --- 655,665 ---- exit_with_path_failure("Cannot have empty path in archived classpaths", NULL); } struct stat st; if (os::stat(path, &st) == 0) { ! if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file if (!os::dir_is_empty(path)) { tty->print_cr("Error: non-empty directory '%s'", path); exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL); } }
*** 691,702 **** void ClassLoader::setup_patch_mod_entries() { Thread* THREAD = Thread::current(); GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix(); int num_of_entries = patch_mod_args->length(); - assert(!DumpSharedSpaces, "DumpSharedSpaces not supported with --patch-module"); - assert(!UseSharedSpaces, "UseSharedSpaces not supported with --patch-module"); // Set up the boot loader's _patch_mod_entries list _patch_mod_entries = new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleClassPathList*>(num_of_entries, true); for (int i = 0; i < num_of_entries; i++) { --- 708,717 ----
*** 849,859 **** ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st, bool throw_exception, bool is_boot_append, TRAPS) { JavaThread* thread = JavaThread::current(); ClassPathEntry* new_entry = NULL; ! if ((st->st_mode & S_IFREG) == S_IFREG) { ResourceMark rm(thread); // Regular file, should be a zip or jimage file // Canonicalized filename char* canonical_path = NEW_RESOURCE_ARRAY_IN_THREAD(thread, char, JVM_MAXPATHLEN); if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { --- 864,874 ---- ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st, bool throw_exception, bool is_boot_append, TRAPS) { JavaThread* thread = JavaThread::current(); ClassPathEntry* new_entry = NULL; ! if ((st->st_mode & S_IFMT) == S_IFREG) { ResourceMark rm(thread); // Regular file, should be a zip or jimage file // Canonicalized filename char* canonical_path = NEW_RESOURCE_ARRAY_IN_THREAD(thread, char, JVM_MAXPATHLEN); if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
*** 912,922 **** // or zip/JAR file cannot be opened) ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bool is_boot_append) { // check for a regular file struct stat st; if (os::stat(path, &st) == 0) { ! if ((st.st_mode & S_IFREG) == S_IFREG) { char canonical_path[JVM_MAXPATHLEN]; if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { char* error_msg = NULL; jzfile* zip; { --- 927,937 ---- // or zip/JAR file cannot be opened) ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bool is_boot_append) { // check for a regular file struct stat st; if (os::stat(path, &st) == 0) { ! if ((st.st_mode & S_IFMT) == S_IFREG) { char canonical_path[JVM_MAXPATHLEN]; if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { char* error_msg = NULL; jzfile* zip; {
*** 1066,1075 **** --- 1081,1091 ---- ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully")); Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32")); + FreeEntry = CAST_TO_FN_PTR(FreeEntry_t, os::dll_lookup(handle, "ZIP_FreeEntry")); // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL || Crc32 == NULL) { vm_exit_during_initialization("Corrupted ZIP library", path);
*** 1393,1402 **** --- 1409,1469 ---- } return NULL; } + #if INCLUDE_CDS + // The following function is only used during CDS dump time. + // It checks if a class can be found in the jar entries of the _patch_mod_entries. + // It does not support non-jar entries. + bool ClassLoader::is_in_patch_module(const char* const file_name) { + assert(DumpSharedSpaces, "dump time only"); + if (_patch_mod_entries == NULL) { + return false; + } + + int num_of_entries = _patch_mod_entries->length(); + char* class_module_name = NULL; + ResourceMark rm; + const char *pkg_name = package_from_name(file_name); + // Using the jimage to obtain the class' module name. + // The ModuleEntryTable cannot be used at this point during dump time + // because the module system hasn't been initialized yet. + if (pkg_name != NULL) { + JImageFile *jimage = _jrt_entry->jimage(); + class_module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name); + } + + if (class_module_name == NULL) { + return false; + } + + // Loop through all the patch module entries looking for module + for (int i = 0; i < num_of_entries; i++) { + ModuleClassPathList* module_cpl = _patch_mod_entries->at(i); + Symbol* module_cpl_name = module_cpl->module_name(); + + if (strcmp(module_cpl_name->as_C_string(), class_module_name) == 0) { + // Class' module has been located, attempt to locate + // the class from the module's ClassPathEntry list. + ClassPathEntry* e = module_cpl->module_first_entry(); + while (e != NULL) { + if (e->is_jar_file()) { + if (e->stream_exists(file_name)) { + return true; + } else { + e = e->next(); + } + } + } + } + } + + return false; + } + #endif // INCLUDE_CDS + instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) { assert(name != NULL, "invariant"); assert(THREAD->is_Java_thread(), "must be a JavaThread"); ResourceMark rm(THREAD);
*** 1418,1429 **** s2 classpath_index = 0; ClassPathEntry* e = NULL; // If DumpSharedSpaces is true boot loader visibility boundaries are set to: // - [jimage] + [_first_append_entry to _last_append_entry] (all path entries). ! // No --patch-module entries or exploded module builds are included since CDS ! // is not supported if --patch-module or exploded module builds are used. // // If search_append_only is true, boot loader visibility boundaries are // set to be _first_append_entry to the end. This includes: // [-Xbootclasspath/a]; [jvmti appended entries] // --- 1485,1496 ---- s2 classpath_index = 0; ClassPathEntry* e = NULL; // If DumpSharedSpaces is true boot loader visibility boundaries are set to: // - [jimage] + [_first_append_entry to _last_append_entry] (all path entries). ! // If a class is found in the --patch-module entries, the class will not be included in the ! // CDS archive. Also, CDS is not supported if exploded module builds are used. // // If search_append_only is true, boot loader visibility boundaries are // set to be _first_append_entry to the end. This includes: // [-Xbootclasspath/a]; [jvmti appended entries] //
*** 1442,1453 **** // Specifications to --patch-module can contain a partial number of classes // that are part of the overall module definition. So if a particular class is not // found within its module specification, the search should continue to Load Attempt #2. // Note: The --patch-module entries are never searched if the boot loader's // visibility boundary is limited to only searching the append entries. ! if (_patch_mod_entries != NULL && !search_append_only && !DumpSharedSpaces) { stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL); } // Load Attempt #2: [jimage | exploded build] if (!search_append_only && (NULL == stream)) { if (has_jrt_entry()) { --- 1509,1529 ---- // Specifications to --patch-module can contain a partial number of classes // that are part of the overall module definition. So if a particular class is not // found within its module specification, the search should continue to Load Attempt #2. // Note: The --patch-module entries are never searched if the boot loader's // visibility boundary is limited to only searching the append entries. ! if (_patch_mod_entries != NULL && !search_append_only) { ! if (!DumpSharedSpaces) { stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL); + } else { + #if INCLUDE_CDS + if (is_in_patch_module(file_name)) { + tty->print_cr("Preload Warning: Skip archiving class %s found in --patch-module entry", class_name); + return NULL; + } + #endif + } } // Load Attempt #2: [jimage | exploded build] if (!search_append_only && (NULL == stream)) { if (has_jrt_entry()) {
*** 1594,1605 **** --- 1670,1730 ---- #endif setup_bootstrap_search_path(); } #if INCLUDE_CDS + // Capture all the --patch-module entries specified during CDS dump time. + // It also captures the non-existing path(s) and the required file(s) during inspecting + // the entries. + void ClassLoader::setup_patch_mod_path() { + assert(DumpSharedSpaces, "only used with -Xshare:dump"); + ResourceMark rm; + GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix(); + if (patch_mod_args != NULL) { + int num_of_entries = patch_mod_args->length(); + for (int i = 0; i < num_of_entries; i++) { + const char* module_name = (patch_mod_args->at(i))->module_name(); + const char* module_path = (patch_mod_args->at(i))->path_string(); + int path_len = (int)strlen(module_path); + int name_len = (int)strlen(module_name); + int buf_len = name_len + path_len + 2; // add 2 for the '=' and NULL terminator + int end = 0; + char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal); + // Iterate over the module's class path entries + for (int start = 0; start < path_len; start = end) { + while (module_path[end] && module_path[end] != os::path_separator()[0]) { + end++; + } + strncpy(buf, &module_path[start], end - start); + buf[end - start] = '\0'; + struct stat st; + if (os::stat(buf, &st) != 0) { + // File not found + _shared_paths_misc_info->add_nonexist_path(buf); + } else { + if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file + vm_exit_during_initialization( + "--patch-module requires a regular file during dumping", buf); + } else { + _shared_paths_misc_info->add_required_file(buf); + } + } + while (module_path[end] == os::path_separator()[0]) { + end++; + } + }; + jio_snprintf(buf, buf_len, "%s=%s", module_name, module_path); + _shared_paths_misc_info->add_patch_mod_classpath((const char*)buf); + _num_patch_mod_prefixes++; + FREE_C_HEAP_ARRAY(char, buf); + } + } + } + void ClassLoader::initialize_shared_path() { if (DumpSharedSpaces) { + setup_patch_mod_path(); ClassLoaderExt::setup_search_paths(); _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check() } } #endif
src/share/vm/classfile/classLoader.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File