diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 95aa54f775f..7dae2cce16e 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -2215,10 +2215,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m // -bootclasspath/a: } else if (match_option(option, "-Xbootclasspath/a:", &tail)) { Arguments::append_sysclasspath(tail); -#if INCLUDE_CDS - MetaspaceShared::disable_optimized_module_handling(); - log_info(cds)("optimized module handling: disabled because bootclasspath was appended"); -#endif // -bootclasspath/p: } else if (match_option(option, "-Xbootclasspath/p:", &tail)) { jio_fprintf(defaultStream::output_stream(), diff --git a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java index 75922c34e65..7b0f4d13e40 100644 --- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java +++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java @@ -64,19 +64,19 @@ public class ClassLoaders { // Creates the built-in class loaders. static { ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get(); + // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute + String append = VM.getSavedProperty("jdk.boot.class.path.append"); + URLClassPath bootUcp = (append != null && !append.isEmpty()) + ? new URLClassPath(append, true) + : null; if (archivedClassLoaders != null) { - // assert VM.getSavedProperty("jdk.boot.class.path.append") == null BOOT_LOADER = (BootClassLoader) archivedClassLoaders.bootLoader(); + BOOT_LOADER.setClassPath(bootUcp); setArchivedServicesCatalog(BOOT_LOADER); PLATFORM_LOADER = (PlatformClassLoader) archivedClassLoaders.platformLoader(); setArchivedServicesCatalog(PLATFORM_LOADER); } else { - // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute - String append = VM.getSavedProperty("jdk.boot.class.path.append"); - URLClassPath ucp = (append != null && !append.isEmpty()) - ? new URLClassPath(append, true) - : null; - BOOT_LOADER = new BootClassLoader(ucp); + BOOT_LOADER = new BootClassLoader(bootUcp); PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER); } // A class path is required when no initial module is specified. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java index eecc218a71a..53de474d9cd 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java @@ -306,7 +306,7 @@ public class OptimizeModuleHandlingTest { .shouldNotContain(OPTIMIZE_ENABLED) .shouldNotContain(OPTIMIZE_DISABLED); }); - tty("10. run with CDS on, with main/test jars on classpath also with -Xbootclasspath/a: should not pass"); + tty("10. run with CDS on, with main/test jars on classpath also with -Xbootclasspath/a: should pass"); TestCommon.run("-Xlog:cds", "-cp", mainJar.toString() + PATH_SEPARATOR + testJar.toString(), "-Xbootclasspath/a:", ".", @@ -314,9 +314,51 @@ public class OptimizeModuleHandlingTest { .assertAbnormalExit(out -> { out.shouldNotContain(CLASS_FOUND_MESSAGE) .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) - .shouldContain(OPTIMIZE_DISABLED) .shouldNotContain(OPTIMIZE_ENABLED) .shouldContain(MAP_FAILED); }); + + // Dump an archive with -Xbootclasspath/a + output = TestCommon.createArchive( + testJar.toString(), + appClasses, + "-Xbootclasspath/a:" + mainJar.toString()); + TestCommon.checkDump(output); + tty("11. run with CDS on, with test jar on classpath and with main jar on -Xbootclasspath/a: should pass"); + TestCommon.run("-Xlog:cds", + "-cp", testJar.toString(), + "-Xbootclasspath/a:" + mainJar.toString(), + MAIN_CLASS) + .assertNormalExit(out -> { + out.shouldNotContain(CLASS_FOUND_MESSAGE) + .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) + .shouldContain(OPTIMIZE_ENABLED); + }); + tty("12. run with CDS on, with main jar on classpath and with test jar on -Xbootclasspath/a: should not pass due to class paths mismatch"); + TestCommon.run("-Xlog:cds", + "-cp", mainJar.toString(), + "-Xbootclasspath/a:" + testJar.toString(), + MAIN_CLASS) + .assertAbnormalExit(out -> { + out.shouldNotContain(CLASS_FOUND_MESSAGE) + .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) + .shouldNotContain(OPTIMIZE_ENABLED) + .shouldContain(MAP_FAILED); + }); + // Dump an archive with only -Xbootclasspath/a + output = TestCommon.createArchive( + null, + appClasses, + "-Xbootclasspath/a:" + mainJar.toString()); + TestCommon.checkDump(output); + tty("13. run with CDS on, with the same -Xbootclasspath/a as dump time and adding a -cp with test.jar: should pass"); + TestCommon.run("-Xlog:cds,class+load", + "-cp", testJar.toString(), + "-Xbootclasspath/a:" + mainJar.toString(), + MAIN_CLASS) + .assertNormalExit(out -> { + out.shouldMatch(MAIN_FROM_CDS) + .shouldContain(OPTIMIZE_ENABLED); + }); } } diff --git a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java index f7d50fd7fe6..71d984d3a63 100644 --- a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java +++ b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java @@ -47,7 +47,8 @@ public class ReplaceCriticalClassesForSubgraphs extends ReplaceCriticalClasses { // CDS should not be disabled -- these critical classes cannot be replaced because // JvmtiExport::early_class_hook_env() is false. - "-subgraph java/lang/module/ResolvedModule jdk.internal.module.ArchivedModuleGraph", + "-subgraph java/lang/module/Configuration java.lang.module.Configuration", + "-subgraph java/lang/ModuleLayer java.lang.ModuleLayer", "-subgraph java/lang/Integer java.lang.Integer$IntegerCache", // Tests for archived full module graph. We cannot use whitebox, which requires appending to bootclasspath.