1 /*
  2  * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 /**
 26  * @test
 27  * @comment the test uses -XX:ArchiveRelocationMode=1 to force relocation.
 28  * @requires vm.cds
 29  * @summary Testing relocation of dynamic CDS archive (during both dump time and run time)
 30  * @comment JDK-8231610 Relocate the CDS archive if it cannot be mapped to the requested address
 31  * @bug 8231610
 32  * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
 33  * @build Hello
 34  * @build jdk.test.whitebox.WhiteBox
 35  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello
 36  * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 37  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. DynamicArchiveRelocationTest
 38  */
 39 
 40 import jdk.test.lib.process.OutputAnalyzer;
 41 import jdk.test.lib.helpers.ClassFileInstaller;
 42 import jtreg.SkippedException;
 43 
 44 public class DynamicArchiveRelocationTest extends DynamicArchiveTestBase {
 45     public static void main(String... args) throws Exception {
 46         try {
 47             testOuter();
 48         } catch (SkippedException s) {
 49             s.printStackTrace();
 50             throw new RuntimeException("Archive mapping should always succeed after JDK-8231610 (did the machine run out of memory?)");
 51         }
 52     }
 53 
 54     static void testOuter() throws Exception {
 55         testInner(true,  false);
 56         testInner(false, true);
 57         testInner(true,  true);
 58     }
 59 
 60     static boolean dump_top_reloc, run_reloc;
 61 
 62     // dump_top_reloc  - force relocation of archive when dumping top  archive
 63     // run_reloc       - force relocation of archive when running
 64     static void testInner(boolean dump_top_reloc, boolean run_reloc) throws Exception {
 65         DynamicArchiveRelocationTest.dump_top_reloc  = dump_top_reloc;
 66         DynamicArchiveRelocationTest.run_reloc       = run_reloc;
 67 
 68         runTest(DynamicArchiveRelocationTest::doTest);
 69     }
 70 
 71     static int caseCount = 0;
 72     static void doTest() throws Exception {
 73         caseCount += 1;
 74         System.out.println("============================================================");
 75         System.out.println("case = " + caseCount
 76                            + ", top_reloc = " + dump_top_reloc
 77                            + ", run = " + run_reloc);
 78         System.out.println("============================================================");
 79 
 80         String appJar = ClassFileInstaller.getJarPath("hello.jar");
 81         String mainClass = "Hello";
 82         String maybeRelocation = "-XX:ArchiveRelocationMode=0";
 83         String alwaysRelocation = "-XX:ArchiveRelocationMode=1";
 84         String dumpTopRelocArg  = dump_top_reloc  ? alwaysRelocation : maybeRelocation;
 85         String runRelocArg      = run_reloc       ? alwaysRelocation : maybeRelocation;
 86         String logArg = "-Xlog:cds=debug,cds+reloc=debug";
 87 
 88         String baseArchiveName = getNewArchiveName("base");
 89         String topArchiveName  = getNewArchiveName("top");
 90 
 91         String runtimeMsg = "Try to map archive(s) at an alternative address";
 92         String unlockArg = "-XX:+UnlockDiagnosticVMOptions";
 93         String relocationModeMsg = "ArchiveRelocationMode: 0";
 94 
 95         // (1) Dump base archive (static)
 96 
 97         TestCommon.dumpBaseArchive(baseArchiveName, unlockArg, logArg)
 98           .shouldContain("Relocating archive from");
 99 
100         // (2) Dump top archive (dynamic)
101 
102         dump2(baseArchiveName, topArchiveName,
103               unlockArg,
104               dumpTopRelocArg,
105               logArg,
106               "-cp", appJar, mainClass)
107             .assertNormalExit(output -> {
108                     if (dump_top_reloc) {
109                         output.shouldContain(runtimeMsg);
110                     } else {
111                         output.shouldContain(relocationModeMsg);
112                     }
113                 });
114 
115         run2(baseArchiveName, topArchiveName,
116              unlockArg,
117              runRelocArg,
118              logArg,
119             "-cp", appJar, mainClass)
120             .assertNormalExit(output -> {
121                     if (run_reloc) {
122                         output.shouldContain(runtimeMsg);
123                     } else {
124                         output.shouldContain(relocationModeMsg);
125                     }
126                 });
127     }
128 }