1 /* 2 * Copyright (c) 2024, 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 "AOT" aliases for traditional CDS command-line options 28 * @requires vm.cds 29 * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes 30 * @build Hello 31 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello 32 * @run driver AOTFlags 33 */ 34 35 import jdk.test.lib.cds.CDSTestUtils; 36 import jdk.test.lib.helpers.ClassFileInstaller; 37 import jdk.test.lib.process.OutputAnalyzer; 38 import jdk.test.lib.process.ProcessTools; 39 40 public class AOTFlags { 41 static String appJar = ClassFileInstaller.getJarPath("hello.jar"); 42 static String aotConfigFile = "hello.aotconfig"; 43 static String aotCacheFile = "hello.aot"; 44 static String helloClass = "Hello"; 45 46 public static void main(String[] args) throws Exception { 47 positiveTests(); 48 negativeTests(); 49 } 50 51 static void positiveTests() throws Exception { 52 //---------------------------------------------------------------------- 53 printTestCase("Training Run"); 54 ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( 55 "-XX:AOTMode=record", 56 "-XX:AOTConfiguration=" + aotConfigFile, 57 "-Xlog:cds=debug", 58 "-cp", appJar, helloClass); 59 60 OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "train"); 61 out.shouldContain("Hello World"); 62 out.shouldContain("AOTConfiguration recorded: " + aotConfigFile); 63 out.shouldHaveExitValue(0); 64 65 //---------------------------------------------------------------------- 66 printTestCase("Assembly Phase (AOTClassLinking unspecified -> should be enabled by default)"); 67 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 68 "-XX:AOTMode=create", 69 "-XX:AOTConfiguration=" + aotConfigFile, 70 "-XX:AOTCache=" + aotCacheFile, 71 "-Xlog:cds", 72 "-cp", appJar); 73 out = CDSTestUtils.executeAndLog(pb, "asm"); 74 out.shouldContain("Dumping shared data to file:"); 75 out.shouldMatch("cds.*hello[.]aot"); 76 out.shouldHaveExitValue(0); 77 78 //---------------------------------------------------------------------- 79 printTestCase("Production Run with AOTCache"); 80 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 81 "-XX:AOTCache=" + aotCacheFile, 82 "-Xlog:cds", 83 "-cp", appJar, helloClass); 84 out = CDSTestUtils.executeAndLog(pb, "prod"); 85 out.shouldContain("Using AOT-linked classes: true (static archive: has aot-linked classes)"); 86 out.shouldContain("Opened AOT cache hello.aot."); 87 out.shouldContain("Hello World"); 88 out.shouldHaveExitValue(0); 89 90 //---------------------------------------------------------------------- 91 printTestCase("AOTMode=off"); 92 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 93 "-XX:AOTCache=" + aotCacheFile, 94 "--show-version", 95 "-Xlog:cds", 96 "-XX:AOTMode=off", 97 "-cp", appJar, helloClass); 98 out = CDSTestUtils.executeAndLog(pb, "prod"); 99 out.shouldNotContain(", sharing"); 100 out.shouldNotContain("Opened AOT cache hello.aot."); 101 out.shouldContain("Hello World"); 102 out.shouldHaveExitValue(0); 103 104 //---------------------------------------------------------------------- 105 printTestCase("AOTMode=auto"); 106 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 107 "-XX:AOTCache=" + aotCacheFile, 108 "--show-version", 109 "-Xlog:cds", 110 "-XX:AOTMode=auto", 111 "-cp", appJar, helloClass); 112 out = CDSTestUtils.executeAndLog(pb, "prod"); 113 out.shouldContain(", sharing"); 114 out.shouldContain("Opened AOT cache hello.aot."); 115 out.shouldContain("Hello World"); 116 out.shouldHaveExitValue(0); 117 118 //---------------------------------------------------------------------- 119 printTestCase("AOTMode=on"); 120 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 121 "-XX:AOTCache=" + aotCacheFile, 122 "--show-version", 123 "-Xlog:cds", 124 "-XX:AOTMode=on", 125 "-cp", appJar, helloClass); 126 out = CDSTestUtils.executeAndLog(pb, "prod"); 127 out.shouldContain(", sharing"); 128 out.shouldContain("Opened AOT cache hello.aot."); 129 out.shouldContain("Hello World"); 130 out.shouldHaveExitValue(0); 131 132 //---------------------------------------------------------------------- 133 printTestCase("Assembly Phase with -XX:-AOTClassLinking"); 134 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 135 "-XX:AOTMode=create", 136 "-XX:-AOTClassLinking", 137 "-XX:AOTConfiguration=" + aotConfigFile, 138 "-XX:AOTCache=" + aotCacheFile, 139 "-Xlog:cds", 140 "-cp", appJar); 141 out = CDSTestUtils.executeAndLog(pb, "asm"); 142 out.shouldContain("Dumping shared data to file:"); 143 out.shouldMatch("cds.*hello[.]aot"); 144 out.shouldHaveExitValue(0); 145 146 //---------------------------------------------------------------------- 147 printTestCase("Production Run with AOTCache, which was created with -XX:-AOTClassLinking"); 148 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 149 "-XX:AOTCache=" + aotCacheFile, 150 "-Xlog:cds", 151 "-cp", appJar, helloClass); 152 out = CDSTestUtils.executeAndLog(pb, "prod"); 153 out.shouldContain("Using AOT-linked classes: false (static archive: no aot-linked classes)"); 154 out.shouldContain("Opened AOT cache hello.aot."); 155 out.shouldContain("Hello World"); 156 out.shouldHaveExitValue(0); 157 } 158 159 static void negativeTests() throws Exception { 160 //---------------------------------------------------------------------- 161 printTestCase("Mixing old and new options"); 162 String mixOldNewErrSuffix = " cannot be used at the same time with -Xshare:on, -Xshare:auto, " 163 + "-Xshare:off, -Xshare:dump, DumpLoadedClassList, SharedClassListFile, " 164 + "or SharedArchiveFile"; 165 166 ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( 167 "-Xshare:off", 168 "-XX:AOTConfiguration=" + aotConfigFile, 169 "-cp", appJar, helloClass); 170 171 OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "neg"); 172 out.shouldContain("Option AOTConfiguration" + mixOldNewErrSuffix); 173 out.shouldNotHaveExitValue(0); 174 175 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 176 "-XX:SharedArchiveFile=" + aotCacheFile, 177 "-XX:AOTCache=" + aotCacheFile, 178 "-cp", appJar, helloClass); 179 out = CDSTestUtils.executeAndLog(pb, "neg"); 180 out.shouldContain("Option AOTCache" + mixOldNewErrSuffix); 181 out.shouldNotHaveExitValue(0); 182 183 //---------------------------------------------------------------------- 184 printTestCase("Use AOTConfiguration without AOTMode"); 185 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 186 "-XX:AOTConfiguration=" + aotConfigFile, 187 "-cp", appJar, helloClass); 188 189 out = CDSTestUtils.executeAndLog(pb, "neg"); 190 out.shouldContain("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create"); 191 out.shouldNotHaveExitValue(0); 192 193 //---------------------------------------------------------------------- 194 printTestCase("Use AOTMode without AOTConfiguration"); 195 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 196 "-XX:AOTMode=record", 197 "-cp", appJar, helloClass); 198 199 out = CDSTestUtils.executeAndLog(pb, "neg"); 200 out.shouldContain("-XX:AOTMode=record cannot be used without setting AOTConfiguration"); 201 202 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 203 "-XX:AOTMode=create", 204 "-cp", appJar, helloClass); 205 206 out = CDSTestUtils.executeAndLog(pb, "neg"); 207 out.shouldContain("-XX:AOTMode=create cannot be used without setting AOTConfiguration"); 208 out.shouldNotHaveExitValue(0); 209 210 //---------------------------------------------------------------------- 211 printTestCase("Bad AOTMode"); 212 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 213 "-XX:AOTMode=foo", 214 "-cp", appJar, helloClass); 215 216 out = CDSTestUtils.executeAndLog(pb, "neg"); 217 out.shouldContain("Unrecognized value foo for AOTMode. Must be one of the following: off, record, create, auto, on"); 218 out.shouldNotHaveExitValue(0); 219 220 //---------------------------------------------------------------------- 221 printTestCase("AOTCache specified with -XX:AOTMode=record"); 222 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 223 "-XX:AOTMode=record", 224 "-XX:AOTConfiguration=" + aotConfigFile, 225 "-XX:AOTCache=" + aotCacheFile, 226 "-cp", appJar, helloClass); 227 228 out = CDSTestUtils.executeAndLog(pb, "neg"); 229 out.shouldContain("AOTCache must not be specified when using -XX:AOTMode=record"); 230 out.shouldNotHaveExitValue(0); 231 232 //---------------------------------------------------------------------- 233 printTestCase("AOTCache not specified with -XX:AOTMode=create"); 234 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 235 "-XX:AOTMode=create", 236 "-XX:AOTConfiguration=" + aotConfigFile, 237 "-cp", appJar, helloClass); 238 239 out = CDSTestUtils.executeAndLog(pb, "neg"); 240 out.shouldContain("AOTCache must be specified when using -XX:AOTMode=create"); 241 out.shouldNotHaveExitValue(0); 242 243 //---------------------------------------------------------------------- 244 printTestCase("No such config file"); 245 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 246 "-XX:AOTMode=create", 247 "-XX:AOTConfiguration=no-such-file", 248 "-XX:AOTCache=" + aotCacheFile, 249 "-cp", appJar, helloClass); 250 251 out = CDSTestUtils.executeAndLog(pb, "neg"); 252 out.shouldContain("Must be a valid AOT configuration generated by the current JVM: no-such-file"); 253 out.shouldNotHaveExitValue(0); 254 255 //---------------------------------------------------------------------- 256 printTestCase("AOTConfiguration file cannot be used as a CDS archive"); 257 258 // first make sure we have a valid aotConfigFile 259 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 260 "-XX:AOTMode=record", 261 "-XX:AOTConfiguration=" + aotConfigFile, 262 "-cp", appJar, helloClass); 263 264 out = CDSTestUtils.executeAndLog(pb, "train"); 265 out.shouldHaveExitValue(0); 266 267 // Cannot use this config file as a AOT cache 268 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 269 "-XX:AOTMode=on", 270 "-XX:AOTCache=" + aotConfigFile, 271 "-cp", appJar, helloClass); 272 273 out = CDSTestUtils.executeAndLog(pb, "neg"); 274 out.shouldContain("Not a valid AOT cache (hello.aotconfig)"); 275 out.shouldNotHaveExitValue(0); 276 277 // Cannot use this config file as a CDS archive 278 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 279 "-Xshare:on", 280 "-XX:SharedArchiveFile=" + aotConfigFile, 281 "-cp", appJar, helloClass); 282 283 out = CDSTestUtils.executeAndLog(pb, "neg"); 284 out.shouldContain("Not a valid archive (hello.aotconfig)"); 285 out.shouldNotHaveExitValue(0); 286 287 //---------------------------------------------------------------------- 288 printTestCase("Classpath mismatch when creating archive"); 289 290 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 291 "-XX:AOTMode=create", 292 "-XX:AOTConfiguration=" + aotConfigFile, 293 "-XX:AOTCache=" + aotCacheFile, 294 "-cp", "noSuchJar.jar"); 295 296 out = CDSTestUtils.executeAndLog(pb, "neg"); 297 out.shouldContain("class path and/or module path are not compatible with the ones " + 298 "specified when the AOTConfiguration file was recorded"); 299 out.shouldContain("Unable to use create AOT cache"); 300 out.shouldHaveExitValue(1); 301 } 302 303 static int testNum = 0; 304 static void printTestCase(String s) { 305 System.out.println("vvvvvvv TEST CASE " + testNum + ": " + s + " starts here vvvvvvv"); 306 testNum++; 307 } 308 }