# HG changeset patch # User jiangli # Date 1511152241 18000 # Node ID a474466c4fdbf1ae212f2ce8b5426288dc99b9c5 # Parent d4af6b80aec350e2b0d18f8c07ce7a19183faf8a 8187118: Remove appending -cp path to the boot class path at AppCDS dump time 8187119: Consolidate record_shared_class_loader_type() and record_result() Summary: Remove -cp path from the boot append list at dump time and other AppCDS cleanups. Reviewed-by: lfoltan, iklam diff -r d4af6b80aec3 -r a474466c4fdb src/hotspot/share/classfile/classLoader.cpp --- a/src/hotspot/share/classfile/classLoader.cpp Fri Nov 17 20:56:14 2017 +0300 +++ b/src/hotspot/share/classfile/classLoader.cpp Sun Nov 19 23:30:41 2017 -0500 @@ -145,9 +145,9 @@ ClassPathEntry* ClassLoader::_jrt_entry = NULL; ClassPathEntry* ClassLoader::_first_append_entry = NULL; ClassPathEntry* ClassLoader::_last_append_entry = NULL; -int ClassLoader::_num_entries = 0; -int ClassLoader::_num_boot_entries = -1; #if INCLUDE_CDS +ClassPathEntry* ClassLoader::_app_classpath_entries = NULL; +ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL; GrowableArray* ClassLoader::_boot_modules_array = NULL; GrowableArray* ClassLoader::_platform_modules_array = NULL; SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL; @@ -660,20 +660,18 @@ void ClassLoader::setup_bootstrap_search_path() { const char* sys_class_path = Arguments::get_sysclasspath(); - const char* java_class_path = Arguments::get_appclasspath(); if (PrintSharedArchiveAndExit) { // Don't print sys_class_path - this is the bootcp of this current VM process, not necessarily // the same as the bootcp of the shared archive. } else { trace_class_path("bootstrap loader class path=", sys_class_path); - trace_class_path("classpath: ", java_class_path); } #if INCLUDE_CDS if (DumpSharedSpaces) { _shared_paths_misc_info->add_boot_classpath(sys_class_path); } #endif - setup_search_path(sys_class_path, true); + setup_boot_search_path(sys_class_path); } #if INCLUDE_CDS @@ -691,6 +689,36 @@ delete checker; return result; } + +void ClassLoader::setup_app_search_path(const char *class_path) { + + assert(DumpSharedSpaces, "Sanity"); + + Thread* THREAD = Thread::current(); + int len = (int)strlen(class_path); + int end = 0; + + // Iterate over class path entries + for (int start = 0; start < len; start = end) { + while (class_path[end] && class_path[end] != os::path_separator()[0]) { + end++; + } + EXCEPTION_MARK; + ResourceMark rm(THREAD); + char* path = NEW_RESOURCE_ARRAY(char, end - start + 1); + strncpy(path, &class_path[start], end - start); + path[end - start] = '\0'; + + check_shared_classpath(path); + + update_class_path_entry_list(path, false, false); + + while (class_path[end] == os::path_separator()[0]) { + end++; + } + } +} + #endif // Construct the array of module/path pairs as specified to --patch-module @@ -764,10 +792,11 @@ return false; } -void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) { +// Set up the _jrt_entry if present and boot append path +void ClassLoader::setup_boot_search_path(const char *class_path) { int len = (int)strlen(class_path); int end = 0; - bool set_base_piece = bootstrap_search; + bool set_base_piece = true; // Iterate over class path entries for (int start = 0; start < len; start = end) { @@ -780,10 +809,10 @@ strncpy(path, &class_path[start], end - start); path[end - start] = '\0'; - // The first time through the bootstrap_search setup, it must be determined - // what the base or core piece of the boot loader search is. Either a java runtime - // image is present or this is an exploded module build situation. if (set_base_piece) { + // The first time through the bootstrap_search setup, it must be determined + // what the base or core piece of the boot loader search is. Either a java runtime + // image is present or this is an exploded module build situation. assert(string_ends_with(path, MODULES_IMAGE_NAME) || string_ends_with(path, JAVA_BASE_NAME), "Incorrect boot loader search path, no java runtime image or " JAVA_BASE_NAME " exploded build"); struct stat st; @@ -797,13 +826,7 @@ assert(_jrt_entry == NULL, "should not setup bootstrap class search path twice"); assert(new_entry != NULL && new_entry->is_modules_image(), "No java runtime image present"); _jrt_entry = new_entry; - ++_num_entries; -#if INCLUDE_CDS - if (DumpSharedSpaces) { - JImageFile *jimage = _jrt_entry->jimage(); - assert(jimage != NULL, "No java runtime image file present"); - } -#endif + assert(_jrt_entry->jimage() != NULL, "No java runtime image"); } } else { // If path does not exist, exit @@ -813,7 +836,7 @@ } else { // Every entry on the system boot class path after the initial base piece, // which is set by os::set_boot_path(), is considered an appended entry. - update_class_path_entry_list(path, false, bootstrap_search); + update_class_path_entry_list(path, false, true); } #if INCLUDE_CDS @@ -968,7 +991,7 @@ return false; } -void ClassLoader::add_to_list(ClassPathEntry *new_entry) { +void ClassLoader::add_to_boot_append_entries(ClassPathEntry *new_entry) { if (new_entry != NULL) { if (_last_append_entry == NULL) { assert(_first_append_entry == NULL, "boot loader's append class path entry list not empty"); @@ -978,11 +1001,48 @@ _last_append_entry = new_entry; } } - _num_entries++; } -void ClassLoader::add_to_list(const char *apath) { - update_class_path_entry_list((char*)apath, false, false); +// Record the path entries specified in -cp during dump time. The recorded +// information will be used at runtime for loading the archived app classes. +// +// Note that at dump time, ClassLoader::_app_classpath_entries are NOT used for +// loading app classes. Instead, the app class are loaded by the +// jdk/internal/loader/ClassLoaders$AppClassLoader instance. +void ClassLoader::add_to_app_classpath_entries(const char* path, + ClassPathEntry* entry, + bool check_for_duplicates) { +#if INCLUDE_CDS + assert(entry != NULL, "ClassPathEntry should not be NULL"); + ClassPathEntry* e = _app_classpath_entries; + if (check_for_duplicates) { + while (e != NULL) { + if (strcmp(e->name(), entry->name()) == 0) { + // entry already exists + return; + } + e = e->next(); + } + } + + // The entry does not exist, add to the list + if (_app_classpath_entries == NULL) { + assert(_last_app_classpath_entry == NULL, "Sanity"); + _app_classpath_entries = _last_app_classpath_entry = entry; + } else { + _last_app_classpath_entry->set_next(entry); + _last_app_classpath_entry = entry; + } + + if (entry->is_jar_file()) { + ClassLoaderExt::process_jar_manifest(entry, check_for_duplicates); + } else { + if (!os::dir_is_empty(path)) { + tty->print_cr("Error: non-empty directory '%s'", path); + exit_with_path_failure("Cannot have non-empty directory in app classpaths", NULL); + } + } +#endif } // Returns true IFF the file/dir exists and the entry was successfully created. @@ -1002,8 +1062,10 @@ // Do not reorder the bootclasspath which would break get_system_package(). // Add new entry to linked list - if (!check_for_duplicates || !contains_append_entry(new_entry->name())) { - ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry); + if (is_boot_append) { + add_to_boot_append_entries(new_entry); + } else { + add_to_app_classpath_entries(path, new_entry, check_for_duplicates); } return true; } else { @@ -1323,6 +1385,7 @@ return NULL; } +// Called by the boot classloader to load classes InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) { assert(name != NULL, "invariant"); assert(THREAD->is_Java_thread(), "must be a JavaThread"); @@ -1402,11 +1465,6 @@ e = _first_append_entry; while (e != NULL) { - if (DumpSharedSpaces && classpath_index >= _num_boot_entries) { - // Do not load any class from the app classpath using the boot loader. Let - // the built-in app class laoder load them. - break; - } stream = e->open_stream(file_name, CHECK_NULL); if (!context.check(stream, classpath_index)) { return NULL; @@ -1442,7 +1500,11 @@ return NULL; } - return context.record_result(name, e, classpath_index, result, THREAD); + if (!add_package(file_name, classpath_index, THREAD)) { + return NULL; + } + + return result; } #if INCLUDE_CDS @@ -1465,7 +1527,9 @@ return source; } -void ClassLoader::record_shared_class_loader_type(InstanceKlass* ik, const ClassFileStream* stream) { +// 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) { assert(DumpSharedSpaces, "sanity"); assert(stream != NULL, "sanity"); @@ -1474,7 +1538,8 @@ return; } - if (stream->source() == NULL) { + char* src = (char*)stream->source(); + if (src == NULL) { if (ik->class_loader() == NULL) { // JFR classes ik->set_shared_classpath_index(0); @@ -1486,56 +1551,42 @@ assert(has_jrt_entry(), "CDS dumping does not support exploded JDK build"); ModuleEntry* module = ik->module(); - ClassPathEntry* e = NULL; - int classpath_index = 0; + int classpath_index = -1; + ResourceMark rm; + char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN); - // Check if the class is from the runtime image - if (module != NULL && (module->location() != NULL) && - (module->location()->starts_with("jrt:"))) { - e = _jrt_entry; - classpath_index = 0; - } else { - classpath_index = 1; - ResourceMark rm; - char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN); - for (e = _first_append_entry; e != NULL; e = e->next()) { - if (get_canonical_path(e->name(), canonical_path, JVM_MAXPATHLEN)) { - char* src = (char*)stream->source(); - // save the path from the file: protocol or the module name from the jrt: protocol - // if no protocol prefix is found, src is the same as stream->source() after the following call - src = skip_uri_protocol(src); - if (strcmp(canonical_path, os::native_path((char*)src)) == 0) { - break; - } - classpath_index ++; + // 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); + 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:"))) { + classpath_index = i; + break; } } - if (e == NULL) { - assert(ik->shared_classpath_index() < 0, - "must be a class from a custom jar which isn't in the class path or boot class path"); - return; - } + } + if (classpath_index < 0) { + // Shared classpath entry table only contains boot class path and -cp path. + // No path entry found for this class. Must be a shared class loaded by the + // user defined classloader. + assert(ik->shared_classpath_index() < 0, "Sanity"); + return; } - if (classpath_index < _num_boot_entries) { - // ik is either: - // 1) a boot class loaded from the runtime image during vm initialization (classpath_index = 0); or - // 2) a user's class from -Xbootclasspath/a (classpath_index > 0) - // In the second case, the classpath_index, classloader_type will be recorded via - // context.record_result() in ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS). - if (classpath_index > 0) { - return; - } - } - - ResourceMark rm; 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(), e, classpath_index, ik, THREAD); + context.record_result(ik->name(), classpath_index, ik, THREAD); } #endif // INCLUDE_CDS @@ -1623,7 +1674,6 @@ #if INCLUDE_CDS void ClassLoader::initialize_shared_path() { if (DumpSharedSpaces) { - _num_boot_entries = _num_entries; ClassLoaderExt::setup_search_paths(); _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check() } diff -r d4af6b80aec3 -r a474466c4fdb src/hotspot/share/classfile/classLoader.hpp --- a/src/hotspot/share/classfile/classLoader.hpp Fri Nov 17 20:56:14 2017 +0300 +++ b/src/hotspot/share/classfile/classLoader.hpp Sun Nov 19 23:30:41 2017 -0500 @@ -237,14 +237,6 @@ // Last entry in linked list of appended ClassPathEntry instances static ClassPathEntry* _last_append_entry; - // Note: _num_entries includes the java runtime image and all - // the entries on the _first_append_entry linked list. - static int _num_entries; - - // number of entries in the boot class path including the - // java runtime image - static int _num_boot_entries; - // Array of module names associated with the boot class loader CDS_ONLY(static GrowableArray* _boot_modules_array;) @@ -254,12 +246,22 @@ // Info used by CDS CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;) + CDS_ONLY(static ClassPathEntry* _app_classpath_entries;) + CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;) + CDS_ONLY(static void setup_app_search_path(const char *class_path);) + static void add_to_app_classpath_entries(const char* path, + ClassPathEntry* entry, + bool check_for_duplicates); + public: + CDS_ONLY(static ClassPathEntry* app_classpath_entries() {return _app_classpath_entries;}) + + protected: // Initialization: // - setup the boot loader's system class path // - setup the boot loader's patch mod entries, if present // - create the ModuleEntry for java.base static void setup_bootstrap_search_path(); - static void setup_search_path(const char *class_path, bool setting_bootstrap); + static void setup_boot_search_path(const char *class_path); static void setup_patch_mod_entries(); static void create_javabase(); @@ -395,7 +397,6 @@ static ClassPathEntry* classpath_entry(int n) { assert(n >= 0, "sanity"); - assert(!has_jrt_entry() || n < _num_entries, "sanity"); if (n == 0) { assert(has_jrt_entry(), "No class path entry at 0 for exploded module builds"); return ClassLoader::_jrt_entry; @@ -414,15 +415,46 @@ } } - static int number_of_classpath_entries() { - return _num_entries; - } - static bool is_in_patch_mod_entries(Symbol* module_name); #if INCLUDE_CDS // Sharing dump and restore + // Helper function used by CDS code to get the number of boot classpath + // entries during shared classpath setup time. + static int num_boot_classpath_entries() { + assert(DumpSharedSpaces, "Should only be called at CDS dump time"); + assert(has_jrt_entry(), "must have a java runtime image"); + int num_entries = 1; // count the runtime image + ClassPathEntry* e = ClassLoader::_first_append_entry; + while (e != NULL) { + num_entries ++; + e = e->next(); + } + return num_entries; + } + + static ClassPathEntry* get_next_boot_classpath_entry(ClassPathEntry* e) { + if (e == ClassLoader::_jrt_entry) { + return ClassLoader::_first_append_entry; + } else { + return e->next(); + } + } + + // Helper function used by CDS code to get the number of app classpath + // entries during shared classpath setup time. + static int num_app_classpath_entries() { + assert(DumpSharedSpaces, "Should only be called at CDS dump time"); + int num_entries = 0; + ClassPathEntry* e= ClassLoader::_app_classpath_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(); @@ -430,7 +462,7 @@ static bool check_shared_paths_misc_info(void* info, int size); static void exit_with_path_failure(const char* error, const char* message); - static void record_shared_class_loader_type(InstanceKlass* ik, const ClassFileStream* stream); + static void record_result(InstanceKlass* ik, const ClassFileStream* stream); #endif static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name, const char* file_name, jlong &size); @@ -446,20 +478,15 @@ static jlong class_link_count(); static jlong class_link_time_ms(); - static void set_first_append_entry(ClassPathEntry* entry); - // indicates if class path already contains a entry (exact match by name) static bool contains_append_entry(const char* name); - // adds a class path list - static void add_to_list(ClassPathEntry* new_entry); + // adds a class path to the boot append entries + static void add_to_boot_append_entries(ClassPathEntry* new_entry); // creates a class path zip entry (returns NULL if JAR file cannot be opened) static ClassPathZipEntry* create_class_path_zip_entry(const char *apath, bool is_boot_append); - // add a path to class path list - static void add_to_list(const char* apath); - static bool string_ends_with(const char* str, const char* str_to_find); // obtain package name from a fully qualified class name diff -r d4af6b80aec3 -r a474466c4fdb src/hotspot/share/classfile/classLoaderExt.hpp --- a/src/hotspot/share/classfile/classLoaderExt.hpp Fri Nov 17 20:56:14 2017 +0300 +++ b/src/hotspot/share/classfile/classLoaderExt.hpp Sun Nov 19 23:30:41 2017 -0500 @@ -50,40 +50,28 @@ return false; } - InstanceKlass* record_result(Symbol* class_name, - ClassPathEntry* e, - const s2 classpath_index, - InstanceKlass* result, TRAPS) { - if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) { + void record_result(Symbol* class_name, + const s2 classpath_index, + InstanceKlass* result, TRAPS) { #if INCLUDE_CDS - if (DumpSharedSpaces) { - oop loader = result->class_loader(); - s2 classloader_type = ClassLoader::BOOT_LOADER; - if (SystemDictionary::is_system_class_loader(loader)) { - classloader_type = ClassLoader::APP_LOADER; - ClassLoaderExt::set_has_app_classes(); - } else if (SystemDictionary::is_platform_class_loader(loader)) { - classloader_type = ClassLoader::PLATFORM_LOADER; - ClassLoaderExt::set_has_platform_classes(); - } - result->set_shared_classpath_index(classpath_index); - result->set_class_loader_type(classloader_type); - } + assert(DumpSharedSpaces, "Sanity"); + oop loader = result->class_loader(); + s2 classloader_type = ClassLoader::BOOT_LOADER; + if (SystemDictionary::is_system_class_loader(loader)) { + classloader_type = ClassLoader::APP_LOADER; + ClassLoaderExt::set_has_app_classes(); + } else if (SystemDictionary::is_platform_class_loader(loader)) { + classloader_type = ClassLoader::PLATFORM_LOADER; + ClassLoaderExt::set_has_platform_classes(); + } + result->set_shared_classpath_index(classpath_index); + result->set_class_loader_type(classloader_type); #endif - return result; - } else { - return NULL; - } } }; - - static void add_class_path_entry(const char* path, bool check_for_duplicates, - ClassPathEntry* new_entry) { - ClassLoader::add_to_list(new_entry); - } static void append_boot_classpath(ClassPathEntry* new_entry) { - ClassLoader::add_to_list(new_entry); + ClassLoader::add_to_boot_append_entries(new_entry); } static void setup_search_paths() {} static bool is_boot_classpath(int classpath_index) { @@ -96,6 +84,7 @@ static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) { return NULL; } + static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates) {} #endif }; diff -r d4af6b80aec3 -r a474466c4fdb src/hotspot/share/classfile/klassFactory.cpp --- a/src/hotspot/share/classfile/klassFactory.cpp Fri Nov 17 20:56:14 2017 +0300 +++ b/src/hotspot/share/classfile/klassFactory.cpp Sun Nov 19 23:30:41 2017 -0500 @@ -231,7 +231,7 @@ #if INCLUDE_CDS if (DumpSharedSpaces) { - ClassLoader::record_shared_class_loader_type(result, stream); + ClassLoader::record_result(result, stream); #if INCLUDE_JVMTI assert(cached_class_file == NULL, "Sanity"); // Archive the class stream data into the optional data section diff -r d4af6b80aec3 -r a474466c4fdb src/hotspot/share/classfile/systemDictionary.cpp --- a/src/hotspot/share/classfile/systemDictionary.cpp Fri Nov 17 20:56:14 2017 +0300 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Sun Nov 19 23:30:41 2017 -0500 @@ -1465,25 +1465,23 @@ // java.base packages in the boot loader's PackageEntryTable. // No class outside of java.base is allowed to be loaded during // this bootstrapping window. - if (!DumpSharedSpaces) { - if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) { - // Class is either in the unnamed package or in - // a named package within the unnamed module. Either - // case is outside of java.base, do not attempt to - // load the class post java.base definition. If - // java.base has not been defined, let the class load - // and its package will be checked later by - // ModuleEntryTable::verify_javabase_packages. - if (ModuleEntryTable::javabase_defined()) { - return NULL; - } - } else { - // Check that the class' package is defined within java.base. - ModuleEntry* mod_entry = pkg_entry->module(); - Symbol* mod_entry_name = mod_entry->name(); - if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) { - return NULL; - } + if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) { + // Class is either in the unnamed package or in + // a named package within the unnamed module. Either + // case is outside of java.base, do not attempt to + // load the class post java.base definition. If + // java.base has not been defined, let the class load + // and its package will be checked later by + // ModuleEntryTable::verify_javabase_packages. + if (ModuleEntryTable::javabase_defined()) { + return NULL; + } + } else { + // Check that the class' package is defined within java.base. + ModuleEntry* mod_entry = pkg_entry->module(); + Symbol* mod_entry_name = mod_entry->name(); + if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) { + return NULL; } } } else { @@ -1501,7 +1499,7 @@ // Prior to bootstrapping's module initialization, never load a class outside // of the boot loader's module path - assert(Universe::is_module_initialized() || DumpSharedSpaces || + assert(Universe::is_module_initialized() || !search_only_bootloader_append, "Attempt to load a class outside of boot loader's module path"); diff -r d4af6b80aec3 -r a474466c4fdb src/hotspot/share/memory/filemap.cpp --- a/src/hotspot/share/memory/filemap.cpp Fri Nov 17 20:56:14 2017 +0300 +++ b/src/hotspot/share/memory/filemap.cpp Sun Nov 19 23:30:41 2017 -0500 @@ -266,32 +266,55 @@ } void FileMapInfo::allocate_classpath_entry_table() { + assert(DumpSharedSpaces, "Sanity"); + Thread* THREAD = Thread::current(); ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + ClassPathEntry* jrt = ClassLoader::get_jrt_entry(); + + assert(jrt != NULL, + "No modular java runtime image present when allocating the CDS classpath entry table"); + size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); // assert ( should be 8 byte aligned??) - int num_entries = ClassLoader::number_of_classpath_entries(); + 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; size_t bytes = entry_size * num_entries; _classpath_entry_table = MetadataFactory::new_array(loader_data, (int)(bytes + 7 / 8), THREAD); _classpath_entry_table_size = num_entries; _classpath_entry_size = entry_size; - assert(ClassLoader::get_jrt_entry() != NULL, - "No modular java runtime image present when allocating the CDS classpath entry table"); - - for (int i=0; iis_jar_file() ? "jar" : "dir")); - + // 1. boot class path + int i = 0; + ClassPathEntry* cpe = jrt; + 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); ent->init(cpe->name(), THREAD); - - if (i > 0) { // No need to do jimage. + if (cpe != jrt) { // No need to do jimage. EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. SharedClassUtil::update_shared_classpath(cpe, ent, THREAD); } + cpe = ClassLoader::get_next_boot_classpath_entry(cpe); + i++; } + assert(i == num_boot_classpath_entries, + "number of boot class path entry mismatch"); + + // 2. app class path + 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); + 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"); } bool FileMapInfo::validate_classpath_entry_table() {