--- old/src/hotspot/share/classfile/systemDictionary.cpp 2020-06-01 16:15:27.154812881 -0700 +++ new/src/hotspot/share/classfile/systemDictionary.cpp 2020-06-01 16:15:26.858801739 -0700 @@ -1228,6 +1228,7 @@ InstanceKlass* SystemDictionary::load_shared_boot_class(Symbol* class_name, PackageEntry* pkg_entry, TRAPS) { + assert(UseSharedSpaces, "Sanity check"); InstanceKlass* ik = SystemDictionaryShared::find_builtin_class(class_name); if (ik != NULL && ik->is_shared_boot_class()) { return load_shared_class(ik, Handle(), Handle(), NULL, pkg_entry, THREAD); @@ -1235,6 +1236,27 @@ return NULL; } +// Check if +// 1) -Xbootclasspath/a: specified or +// 2) --module-path at runtime +// so avoid checking class visibility for builtin loaders. +bool need_to_check_shared_class_visibility() { + static int check_continue = -1; + if (check_continue == -1) { + const char *classpath_append = Arguments::get_jdk_boot_class_path_append(); + const char *module_path = Arguments::get_property("jdk.module.path"); + log_info(cds)("-Xbootclasspath/a: = %s", classpath_append != NULL ? classpath_append : "nil"); + log_info(cds)("--module-path = %s", module_path != NULL ? module_path : "nil"); + if ((classpath_append == NULL || strlen(classpath_append) == 0) && + (module_path == NULL || strlen(module_path) == 0)) { + check_continue = 0; + } else { + check_continue = 1; + } + } + return check_continue == 1; +} + // Check if a shared class can be loaded by the specific classloader: // // NULL classloader: @@ -1247,18 +1269,29 @@ Handle class_loader, TRAPS) { assert(!ModuleEntryTable::javabase_moduleEntry()->is_patched(), "Cannot use sharing if java.base is patched"); - ResourceMark rm(THREAD); - int path_index = ik->shared_classpath_index(); - ClassLoaderData* loader_data = class_loader_data(class_loader); - if (path_index < 0) { + if (ik->shared_classpath_index() < 0) { // path_index < 0 indicates that the class is intended for a custom loader // and should not be loaded by boot/platform/app loaders - if (loader_data->is_builtin_class_loader_data()) { + if (is_builtin_class_loader(class_loader())) { return false; } else { return true; - } + } + } + bool cont = need_to_check_shared_class_visibility(); + if (!cont) { + assert(SystemDictionary::is_shared_class_visible_impl(class_name, ik, pkg_entry, class_loader, THREAD), "Sanity check"); + return true; } + return is_shared_class_visible_impl(class_name, ik, pkg_entry, class_loader, THREAD); +} + +bool SystemDictionary::is_shared_class_visible_impl(Symbol* class_name, + InstanceKlass* ik, + PackageEntry* pkg_entry, + Handle class_loader, TRAPS) { + ClassLoaderData* loader_data = class_loader_data(class_loader); + int path_index = ik->shared_classpath_index(); SharedClassPathEntry* ent = (SharedClassPathEntry*)FileMapInfo::shared_path(path_index); if (!Universe::is_module_initialized()) { @@ -1556,12 +1589,14 @@ // Search for classes in the CDS archive. InstanceKlass* k = NULL; - { + #if INCLUDE_CDS + if (UseSharedSpaces) + { PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time()); k = load_shared_boot_class(class_name, pkg_entry, THREAD); -#endif } +#endif if (k == NULL) { // Use VM class loader --- old/src/hotspot/share/classfile/systemDictionary.hpp 2020-06-01 16:15:27.734834714 -0700 +++ new/src/hotspot/share/classfile/systemDictionary.hpp 2020-06-01 16:15:27.438823572 -0700 @@ -631,6 +631,9 @@ static bool is_shared_class_visible(Symbol* class_name, InstanceKlass* ik, PackageEntry* pkg_entry, Handle class_loader, TRAPS); + static bool is_shared_class_visible_impl(Symbol* class_name, InstanceKlass* ik, + PackageEntry* pkg_entry, + Handle class_loader, TRAPS); static bool check_shared_class_super_type(InstanceKlass* child, InstanceKlass* super, Handle class_loader, Handle protection_domain, bool is_superclass, TRAPS); --- old/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP.java 2020-06-01 16:15:28.294855795 -0700 +++ new/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP.java 2020-06-01 16:15:27.998844652 -0700 @@ -104,7 +104,7 @@ "--module-path", moduleDir.toString(), "-m", MAIN_MODULE); TestCommon.checkDump(output); - String prefix[] = {"-Djava.class.path=", "-Xlog:class+load=trace"}; + String prefix[] = {"-Djava.class.path=", "-Xlog:cds,class+load=trace"}; prefix = TestCommon.concat(prefix, extra_runtime_args); // run with the archive with the --module-path the same as the one during @@ -115,7 +115,8 @@ MAIN_MODULE) // -m .assertNormalExit(out -> { out.shouldContain("[class,load] com.greetings.Main source: shared objects file") - .shouldContain("[class,load] org.astro.World source: shared objects file"); + .shouldContain("[class,load] org.astro.World source: shared objects file") + .shouldContain("--module-path = " + moduleDir.toString()); }); // run with the archive with the --module-path different from the one during @@ -126,7 +127,8 @@ MAIN_MODULE) // -m .assertNormalExit(out -> { out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar") - .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); + .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar") + .shouldContain("--module-path = " + moduleDir2.toString()); }); // create an archive with modular jar files in both -cp and --module-path @@ -143,24 +145,26 @@ // during dump time, the classes in the jar files after the -cp won't be // archived. Therefore, the classes won't be loaded from the archive but // will be loaded from the jar files. - TestCommon.run("-Xlog:class+load=trace", + TestCommon.run("-Xlog:cds,class+load=trace", "-cp", jars, "--module-path", moduleDir.toString(), MAIN_CLASS, "-m", MAIN_MODULE) .assertNormalExit(out -> { out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar") - .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); + .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar") + .shouldContain("--module-path = " + moduleDir.toString()); }); // similar to the above case but without the main class name. The classes // should be loaded from the archive. - TestCommon.run("-Xlog:class+load=trace", + TestCommon.run("-Xlog:cds,class+load=trace", "-cp", jars, "--module-path", moduleDir.toString(), "-m", MAIN_MODULE) .assertNormalExit( "[class,load] com.greetings.Main source: shared objects file", - "[class,load] org.astro.World source: shared objects file"); + "[class,load] org.astro.World source: shared objects file", + "--module-path = " + moduleDir.toString()); // create an archive with two modular jars in the --module-path output = TestCommon.createArchive( @@ -173,15 +177,28 @@ // org.astro module in a different location. // The org.astro.World class should be loaded from the jar. // The Main class should still be loaded from the archive. - jars = destJar.toString() + System.getProperty("path.separator") + + final String mjars = destJar.toString() + System.getProperty("path.separator") + mainJar.toString(); TestCommon.runWithModules(prefix, null, // --upgrade-module-path - jars, // --module-path + mjars, // --module-path MAIN_MODULE) // -m .assertNormalExit(out -> { out.shouldContain("[class,load] com.greetings.Main source: shared objects file") - .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); + .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar") + .shouldContain("--module-path = " + mjars); }); + // run with CDS off, '--module-path = ' should not be printed out on output + output = TestCommon.exec(mjars, + "-Xshare:off", + "-Xlog:cds,class+load=trace", + "--module-path", + mjars, + "-m", + MAIN_MODULE); + output.shouldNotContain("sharing"); + output.shouldNotContain("--module-path = " + mjars); + output.shouldMatch(".class,load. com.greetings.Main source: .*com.greetings.jar"); + output.shouldMatch(".class.load. org.astro.World source:.*org.astro.jar"); } }