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 String hasTrainingDataPattern = "MethodTrainingData *= *[1-9]"; 53 String noTrainingDataPattern = "MethodTrainingData *= *0"; 54 String hasCachedCodePattern = "Shared file region .cc. .: *[1-9]"; 55 String noCachedCodePattern = "Shared file region .cc. .: *0"; 56 String hasMappedCachedCodePattern = "Mapped [0-9]+ bytes at address 0x[0-9a-f]+ from AOT Code Cache"; 57 58 //---------------------------------------------------------------------- 59 printTestCase("Training Run"); 60 ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( 61 "-XX:AOTMode=record", 62 "-XX:AOTConfiguration=" + aotConfigFile, 63 "-Xlog:cds=debug", 64 "-cp", appJar, helloClass); 65 66 OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "train"); 67 out.shouldContain("Hello World"); 68 out.shouldContain("AOTConfiguration recorded: " + aotConfigFile); 69 out.shouldMatch(hasTrainingDataPattern); 70 out.shouldMatch(noCachedCodePattern); 71 out.shouldHaveExitValue(0); 72 73 //---------------------------------------------------------------------- 74 printTestCase("Assembly Phase (AOTClassLinking unspecified -> should be enabled by default)"); 75 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 76 "-XX:AOTMode=create", 77 "-XX:AOTConfiguration=" + aotConfigFile, 78 "-XX:AOTCache=" + aotCacheFile, 79 "-Xlog:cds", 80 "-cp", appJar); 81 out = CDSTestUtils.executeAndLog(pb, "asm"); 82 out.shouldContain("Dumping shared data to file:"); 83 out.shouldMatch("cds.*hello[.]aot"); 84 out.shouldMatch(hasTrainingDataPattern); 85 out.shouldMatch(hasCachedCodePattern); 86 out.shouldHaveExitValue(0); 87 88 //---------------------------------------------------------------------- 89 printTestCase("Production Run with AOTCache"); 90 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 91 "-XX:AOTCache=" + aotCacheFile, 92 "-Xlog:cds", 93 "-Xlog:scc*", 94 "-cp", appJar, helloClass); 95 out = CDSTestUtils.executeAndLog(pb, "prod"); 96 out.shouldContain("Using AOT-linked classes: true (static archive: has aot-linked classes)"); 97 out.shouldContain("Opened AOT cache hello.aot."); 98 out.shouldContain("Hello World"); 99 out.shouldMatch(hasMappedCachedCodePattern); 100 out.shouldHaveExitValue(0); 101 102 //---------------------------------------------------------------------- 103 printTestCase("AOTMode=off"); 104 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 105 "-XX:AOTCache=" + aotCacheFile, 106 "--show-version", 107 "-Xlog:cds", 108 "-XX:AOTMode=off", 109 "-cp", appJar, helloClass); 110 out = CDSTestUtils.executeAndLog(pb, "prod"); 111 out.shouldNotContain(", sharing"); 112 out.shouldNotContain("Opened AOT cache hello.aot."); 113 out.shouldContain("Hello World"); 114 out.shouldHaveExitValue(0); 115 116 //---------------------------------------------------------------------- 117 printTestCase("AOTMode=auto"); 118 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 119 "-XX:AOTCache=" + aotCacheFile, 120 "--show-version", 121 "-Xlog:cds", 122 "-XX:AOTMode=auto", 123 "-cp", appJar, helloClass); 124 out = CDSTestUtils.executeAndLog(pb, "prod"); 125 out.shouldContain(", sharing"); 126 out.shouldContain("Opened AOT cache hello.aot."); 127 out.shouldContain("Hello World"); 128 out.shouldHaveExitValue(0); 129 130 //---------------------------------------------------------------------- 131 printTestCase("AOTMode=on"); 132 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 133 "-XX:AOTCache=" + aotCacheFile, 134 "--show-version", 135 "-Xlog:cds", 136 "-XX:AOTMode=on", 137 "-cp", appJar, helloClass); 138 out = CDSTestUtils.executeAndLog(pb, "prod"); 139 out.shouldContain(", sharing"); 140 out.shouldContain("Opened AOT cache hello.aot."); 141 out.shouldContain("Hello World"); 142 out.shouldHaveExitValue(0); 143 144 //---------------------------------------------------------------------- 145 printTestCase("Assembly Phase with -XX:-AOTClassLinking"); 146 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 147 "-XX:AOTMode=create", 148 "-XX:-AOTClassLinking", 149 "-XX:AOTConfiguration=" + aotConfigFile, 150 "-XX:AOTCache=" + aotCacheFile, 151 "-Xlog:cds=debug", 152 "-cp", appJar); 153 out = CDSTestUtils.executeAndLog(pb, "asm"); 154 out.shouldContain("Dumping shared data to file:"); 155 out.shouldMatch("cds.*hello[.]aot"); 156 out.shouldMatch(noTrainingDataPattern); 157 out.shouldMatch(noCachedCodePattern); 158 out.shouldHaveExitValue(0); 159 160 //---------------------------------------------------------------------- 161 printTestCase("Production Run with AOTCache, which was created with -XX:-AOTClassLinking"); 162 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 163 "-XX:AOTCache=" + aotCacheFile, 164 "-Xlog:cds", 165 "-Xlog:scc*", 166 "-cp", appJar, helloClass); 167 out = CDSTestUtils.executeAndLog(pb, "prod"); 168 out.shouldContain("Using AOT-linked classes: false (static archive: no aot-linked classes)"); 169 out.shouldContain("Opened AOT cache hello.aot."); 170 out.shouldContain("Hello World"); 171 out.shouldNotMatch(hasMappedCachedCodePattern); 172 out.shouldHaveExitValue(0); 173 174 //---------------------------------------------------------------------- 175 printTestCase("Training run with -XX:-AOTClassLinking, but assembly run with -XX:+AOTClassLinking"); 176 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 177 "-XX:AOTMode=record", 178 "-XX:-AOTClassLinking", 179 "-XX:AOTConfiguration=" + aotConfigFile, 180 "-Xlog:cds=debug", 181 "-cp", appJar, helloClass); 182 out = CDSTestUtils.executeAndLog(pb, "train"); 183 out.shouldContain("Hello World"); 184 out.shouldContain("AOTConfiguration recorded: " + aotConfigFile); 185 out.shouldHaveExitValue(0); 186 187 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 188 "-XX:AOTMode=create", 189 "-XX:+AOTClassLinking", 190 "-XX:AOTConfiguration=" + aotConfigFile, 191 "-XX:AOTCache=" + aotCacheFile, 192 "-Xlog:cds=debug", 193 "-cp", appJar); 194 out = CDSTestUtils.executeAndLog(pb, "asm"); 195 out.shouldContain("Dumping shared data to file:"); 196 out.shouldMatch("cds.*hello[.]aot"); 197 out.shouldHaveExitValue(0); 198 } 199 200 static void negativeTests() throws Exception { 201 //---------------------------------------------------------------------- 202 printTestCase("Mixing old and new options"); 203 String mixOldNewErrSuffix = " cannot be used at the same time with -Xshare:on, -Xshare:auto, " 204 + "-Xshare:off, -Xshare:dump, DumpLoadedClassList, SharedClassListFile, " 205 + "or SharedArchiveFile"; 206 207 ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( 208 "-Xshare:off", 209 "-XX:AOTConfiguration=" + aotConfigFile, 210 "-cp", appJar, helloClass); 211 212 OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "neg"); 213 out.shouldContain("Option AOTConfiguration" + mixOldNewErrSuffix); 214 out.shouldNotHaveExitValue(0); 215 216 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 217 "-XX:SharedArchiveFile=" + aotCacheFile, 218 "-XX:AOTCache=" + aotCacheFile, 219 "-cp", appJar, helloClass); 220 out = CDSTestUtils.executeAndLog(pb, "neg"); 221 out.shouldContain("Option AOTCache" + mixOldNewErrSuffix); 222 out.shouldNotHaveExitValue(0); 223 224 //---------------------------------------------------------------------- 225 printTestCase("Use AOTConfiguration without AOTMode"); 226 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 227 "-XX:AOTConfiguration=" + aotConfigFile, 228 "-cp", appJar, helloClass); 229 230 out = CDSTestUtils.executeAndLog(pb, "neg"); 231 out.shouldContain("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create"); 232 out.shouldNotHaveExitValue(0); 233 234 //---------------------------------------------------------------------- 235 printTestCase("Use AOTMode without AOTConfiguration"); 236 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 237 "-XX:AOTMode=record", 238 "-cp", appJar, helloClass); 239 240 out = CDSTestUtils.executeAndLog(pb, "neg"); 241 out.shouldContain("-XX:AOTMode=record cannot be used without setting AOTConfiguration"); 242 243 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 244 "-XX:AOTMode=create", 245 "-cp", appJar, helloClass); 246 247 out = CDSTestUtils.executeAndLog(pb, "neg"); 248 out.shouldContain("-XX:AOTMode=create cannot be used without setting AOTConfiguration"); 249 out.shouldNotHaveExitValue(0); 250 251 //---------------------------------------------------------------------- 252 printTestCase("Bad AOTMode"); 253 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 254 "-XX:AOTMode=foo", 255 "-cp", appJar, helloClass); 256 257 out = CDSTestUtils.executeAndLog(pb, "neg"); 258 out.shouldContain("Unrecognized value foo for AOTMode. Must be one of the following: off, record, create, auto, on"); 259 out.shouldNotHaveExitValue(0); 260 261 //---------------------------------------------------------------------- 262 printTestCase("AOTCache specified with -XX:AOTMode=record"); 263 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 264 "-XX:AOTMode=record", 265 "-XX:AOTConfiguration=" + aotConfigFile, 266 "-XX:AOTCache=" + aotCacheFile, 267 "-cp", appJar, helloClass); 268 269 out = CDSTestUtils.executeAndLog(pb, "neg"); 270 out.shouldContain("AOTCache must not be specified when using -XX:AOTMode=record"); 271 out.shouldNotHaveExitValue(0); 272 273 //---------------------------------------------------------------------- 274 printTestCase("AOTCache not specified with -XX:AOTMode=create"); 275 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 276 "-XX:AOTMode=create", 277 "-XX:AOTConfiguration=" + aotConfigFile, 278 "-cp", appJar, helloClass); 279 280 out = CDSTestUtils.executeAndLog(pb, "neg"); 281 out.shouldContain("AOTCache must be specified when using -XX:AOTMode=create"); 282 out.shouldNotHaveExitValue(0); 283 284 //---------------------------------------------------------------------- 285 printTestCase("No such config file"); 286 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 287 "-XX:AOTMode=create", 288 "-XX:AOTConfiguration=no-such-file", 289 "-XX:AOTCache=" + aotCacheFile, 290 "-cp", appJar, helloClass); 291 292 out = CDSTestUtils.executeAndLog(pb, "neg"); 293 out.shouldContain("Must be a valid AOT configuration generated by the current JVM: no-such-file"); 294 out.shouldNotHaveExitValue(0); 295 296 //---------------------------------------------------------------------- 297 printTestCase("AOTConfiguration file cannot be used as a CDS archive"); 298 299 // first make sure we have a valid aotConfigFile 300 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 301 "-XX:AOTMode=record", 302 "-XX:AOTConfiguration=" + aotConfigFile, 303 "-cp", appJar, helloClass); 304 305 out = CDSTestUtils.executeAndLog(pb, "train"); 306 out.shouldHaveExitValue(0); 307 308 // Cannot use this config file as a AOT cache 309 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 310 "-XX:AOTMode=on", 311 "-XX:AOTCache=" + aotConfigFile, 312 "-cp", appJar, helloClass); 313 314 out = CDSTestUtils.executeAndLog(pb, "neg"); 315 out.shouldContain("Not a valid AOT cache (hello.aotconfig)"); 316 out.shouldNotHaveExitValue(0); 317 318 // Cannot use this config file as a CDS archive 319 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 320 "-Xshare:on", 321 "-XX:SharedArchiveFile=" + aotConfigFile, 322 "-cp", appJar, helloClass); 323 324 out = CDSTestUtils.executeAndLog(pb, "neg"); 325 out.shouldContain("Not a valid archive (hello.aotconfig)"); 326 out.shouldNotHaveExitValue(0); 327 328 //---------------------------------------------------------------------- 329 printTestCase("Classpath mismatch when creating archive"); 330 331 pb = ProcessTools.createLimitedTestJavaProcessBuilder( 332 "-XX:AOTMode=create", 333 "-XX:AOTConfiguration=" + aotConfigFile, 334 "-XX:AOTCache=" + aotCacheFile, 335 "-cp", "noSuchJar.jar"); 336 337 out = CDSTestUtils.executeAndLog(pb, "neg"); 338 out.shouldContain("class path and/or module path are not compatible with the ones " + 339 "specified when the AOTConfiguration file was recorded"); 340 out.shouldContain("Unable to use create AOT cache"); 341 out.shouldHaveExitValue(1); 342 } 343 344 static int testNum = 0; 345 static void printTestCase(String s) { 346 System.out.println("vvvvvvv TEST CASE " + testNum + ": " + s + ": starts here vvvvvvv"); 347 testNum++; 348 } 349 }