1 /*
  2  * Copyright (c) 2018, 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  * @summary Test primitive box caches integrity in various scenarios (IntegerCache etc)
 28  * @requires vm.cds.write.archived.java.heap
 29  * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/cds/appcds
 30  * @compile --add-exports java.base/jdk.internal.misc=ALL-UNNAMED CheckIntegerCacheApp.java ArchivedIntegerHolder.java
 31  * @build jdk.test.whitebox.WhiteBox
 32  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar jdk.test.whitebox.WhiteBox
 33  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boxCache.jar CheckIntegerCacheApp
 34  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boxCache-boot.jar ArchivedIntegerHolder
 35  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:./WhiteBox.jar ArchivedIntegerCacheTest
 36  */
 37 
 38 import java.nio.file.Files;
 39 import java.nio.file.Path;
 40 import java.nio.file.Paths;
 41 import jdk.test.lib.cds.CDSTestUtils;
 42 import jdk.test.lib.process.OutputAnalyzer;
 43 import jdk.test.lib.helpers.ClassFileInstaller;
 44 import jdk.test.whitebox.WhiteBox;
 45 
 46 public class ArchivedIntegerCacheTest {
 47     private static WhiteBox WB = WhiteBox.getWhiteBox();
 48 
 49     public static String[] mixArgs(String... args) {
 50         String bootJar = ClassFileInstaller.getJarPath("boxCache-boot.jar");
 51 
 52         String[] newArgs = new String[args.length + 5];
 53         newArgs[0] = "--add-exports";
 54         newArgs[1] = "java.base/jdk.internal.misc=ALL-UNNAMED";
 55         newArgs[2] = "-Xbootclasspath/a:" + bootJar;
 56         newArgs[3] = "-XX:+IgnoreUnrecognizedVMOptions";
 57         newArgs[4] = "-XX:ArchiveHeapTestClass=ArchivedIntegerHolder";
 58         System.arraycopy(args, 0, newArgs, 5, args.length);
 59         return newArgs;
 60     }
 61 
 62     public static void main(String[] args) throws Exception {
 63         String appJar = ClassFileInstaller.getJarPath("boxCache.jar");
 64 
 65         Path userDir = Paths.get(CDSTestUtils.getOutputDir());
 66         Path moduleDir = Files.createTempDirectory(userDir, "mods");
 67 
 68         //
 69         // Dump default archive
 70         //
 71         OutputAnalyzer output = TestCommon.dump(appJar,
 72                 TestCommon.list("CheckIntegerCacheApp"),
 73                 mixArgs());
 74         TestCommon.checkDump(output);
 75 
 76         // Test case 1)
 77         // - Default options
 78         System.out.println("----------------------- Test case 1 ----------------------");
 79         output = TestCommon.exec(appJar,
 80                 mixArgs("CheckIntegerCacheApp", "127"));
 81         TestCommon.checkExec(output);
 82 
 83         // Test case 2)
 84         // - Default archive
 85         // - Larger -XX:AutoBoxCacheMax
 86         System.out.println("----------------------- Test case 2 ----------------------");
 87         output = TestCommon.exec(appJar,
 88                 mixArgs("-XX:AutoBoxCacheMax=20000",
 89                         "CheckIntegerCacheApp", "20000"));
 90         TestCommon.checkExec(output);
 91 
 92         //
 93         // Dump with -XX:AutoBoxCacheMax specified
 94         //
 95         output = TestCommon.dump(appJar,
 96                 TestCommon.list("CheckIntegerCacheApp"),
 97                 mixArgs("-XX:AutoBoxCacheMax=20000"));
 98         TestCommon.checkDump(output);
 99 
100         // Test case 3)
101         // - Large archived cache
102         // - Default options
103         System.out.println("----------------------- Test case 3 ----------------------");
104         output = TestCommon.exec(appJar,
105                 mixArgs("--module-path", moduleDir.toString(),
106                         "CheckIntegerCacheApp", "127"));
107         TestCommon.checkExec(output);
108 
109 
110         // Test case 4)
111         // - Large archived cache
112         // - Matching options
113         System.out.println("----------------------- Test case 4 ----------------------");
114         output = TestCommon.exec(appJar,
115                 mixArgs("--module-path", moduleDir.toString(),
116                         "-XX:AutoBoxCacheMax=20000",
117                         "CheckIntegerCacheApp", "20000"));
118         TestCommon.checkExec(output);
119 
120         // Test case 5)
121         // - Large archived cache
122         // - Larger requested cache
123         System.out.println("----------------------- Test case 5 ----------------------");
124         output = TestCommon.exec(appJar,
125                 mixArgs("--module-path", moduleDir.toString(),
126                         "-XX:AutoBoxCacheMax=30000",
127                         "CheckIntegerCacheApp", "30000"));
128         TestCommon.checkExec(output);
129 
130         // Test case 6)
131         // - Cache is too large to archive
132         output = TestCommon.dump(appJar,
133                 TestCommon.list("CheckIntegerCacheApp"),
134                 mixArgs("-XX:AutoBoxCacheMax=2000000",
135                         "-Xmx1g",
136                         "-XX:NewSize=1g",
137                         "-Xlog:cds+heap=info",
138                         "-Xlog:gc+region+cds",
139                         "-Xlog:gc+region=trace"));
140         if (WB.canWriteMappedJavaHeapArchive()) {
141             // The mapping AOT heap archiving mechanism is unable to cache larger objects.
142             TestCommon.checkDump(output, "Cannot archive the sub-graph referenced from [Ljava.lang.Integer; object");
143         }
144     }
145 }