1 /* 2 * Copyright (c) 2024, 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 CDS should fail to load if production time GC flags do not match training run. 28 * @requires vm.flagless 29 * @requires vm.cds.write.archived.java.heap 30 * @requires vm.gc.ZSinglegen 31 * @requires vm.gc.Serial 32 * @requires vm.gc.Parallel 33 * @library /test/jdk/lib/testlibrary /test/lib 34 * @build LeydenGCFlags 35 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HelloApp 36 * @run driver LeydenGCFlags 37 */ 38 39 import jdk.test.lib.cds.CDSAppTester; 40 import jdk.test.lib.helpers.ClassFileInstaller; 41 import jdk.test.lib.process.OutputAnalyzer; 42 import jdk.test.lib.StringArrayUtils; 43 44 public class LeydenGCFlags { 45 static final String appJar = ClassFileInstaller.getJarPath("app.jar"); 46 static final String mainClass = "HelloApp"; 47 static final String ERROR_GC_SUPPORTED = "Cannot create the CacheDataStore: UseCompressedClassPointers must be enabled, and collector must be G1, Parallel, Serial, or Epsilon"; 48 static final String ERROR_GC_MISMATCH = "CDS archive has aot-linked classes. It cannot be used because GC used during dump time (.*) is not the same as runtime (.*)"; 49 static final String ERROR_COOP_MISMATCH = "Disable Startup Code Cache: 'HelloApp.cds.code' was created with CompressedOops::shift.. = .* vs current .*"; 50 51 static String trainingArgs[]; 52 static String productionArgs[]; 53 static boolean shouldFailDump; 54 static boolean shouldFailRun; 55 static String productFailPattern; 56 57 public static void main(String[] args) throws Exception { 58 // ZGC not supported for now 59 fail_dump("-XX:+UseZGC", "-Xmx8g", ERROR_GC_SUPPORTED); 60 61 // Serial and Parallel collector are allowed to be used, as long as the same one is used 62 // between training and production 63 good("-XX:+UseSerialGC", "-XX:+UseSerialGC"); 64 good("-XX:+UseParallelGC", "-XX:+UseParallelGC"); 65 66 // Fail if production uses a different collector than training 67 fail_run("-XX:+UseParallelGC", "-XX:+UseG1GC", ERROR_GC_MISMATCH ); 68 fail_run(null, "-XX:+UseParallelGC", ERROR_GC_MISMATCH ); 69 70 71 if (false) { // Disabled for now, as on MacOS we cannot guarantee to get differnt coop encodings 72 // Different oop encodings 73 fail_run(array("-XX:-UseCompatibleCompressedOops", "-Xmx128m"), 74 array("-XX:-UseCompatibleCompressedOops","-Xmx8g"), 75 ERROR_COOP_MISMATCH); 76 fail_run(array("-XX:-UseCompatibleCompressedOops", "-Xmx8g"), 77 array("-XX:-UseCompatibleCompressedOops","-Xmx128m"), 78 ERROR_COOP_MISMATCH); 79 } 80 81 // FIXME -- this causes 82 // java.lang.invoke.WrongMethodTypeException: handle's method type ()Object but found ()Object 83 /* fail_run(null, "NoSuchApp"); */ 84 } 85 86 static String[] array(String... strings) { 87 return strings; 88 } 89 static void good(Object t, Object p) throws Exception { 90 shouldFailDump = false; 91 shouldFailRun = false; 92 run(t, p); 93 } 94 95 static void fail_dump(Object t, Object p, String regexp) throws Exception { 96 shouldFailDump = true; 97 shouldFailRun = true; 98 productFailPattern = regexp; 99 trainingArgs = makeArgs(t); 100 productionArgs = makeArgs(p); 101 Tester tester = new Tester(); 102 tester.setCheckExitValue(false); 103 tester.run(new String[] {"LEYDEN_TRAINONLY"} ); 104 } 105 106 static void fail_run(Object t, Object p, String regexp) throws Exception { 107 shouldFailDump = false; 108 shouldFailRun = true; 109 productFailPattern = regexp; 110 run(t, p); 111 } 112 113 static void run(Object t, Object p) throws Exception { 114 trainingArgs = makeArgs(t); 115 productionArgs = makeArgs(p); 116 Tester tester = new Tester(); 117 tester.run(new String[] {"LEYDEN"} ); 118 } 119 120 static String[] makeArgs(Object o) { 121 if (o == null) { 122 return new String[0]; 123 } 124 if (o instanceof String[]) { 125 return (String[])o; 126 } else { 127 return new String[] { (String)o }; 128 } 129 } 130 131 static class Tester extends CDSAppTester { 132 public Tester() { 133 super(mainClass); 134 } 135 136 @Override 137 public String classpath(RunMode runMode) { 138 return appJar; 139 } 140 141 @Override 142 public String[] appCommandLine(RunMode runMode) { 143 if (runMode.isProductionRun()) { 144 return StringArrayUtils.concat(productionArgs, "-Xshare:auto", mainClass); 145 } else { 146 return StringArrayUtils.concat(trainingArgs, mainClass); 147 } 148 } 149 150 @Override 151 public void checkExecution(OutputAnalyzer out, RunMode runMode) { 152 if (shouldFailDump) { 153 if (runMode != RunMode.PRODUCTION) { 154 out.shouldMatch(productFailPattern); 155 out.shouldHaveExitValue(1); 156 } 157 } else if (shouldFailRun) { 158 if (runMode == RunMode.PRODUCTION) { 159 out.shouldMatch(productFailPattern); 160 //out.shouldHaveExitValue(1); TODO VM should enable -Xshare:on by default 161 } 162 } else { 163 if (runMode != RunMode.TRAINING1) { 164 out.shouldContain("Hello Leyden"); 165 } 166 167 if (runMode == RunMode.TRAINING || runMode == RunMode.TRAINING1) { 168 // We should dump the heap even if the collector is not G1 169 out.shouldContain("Shared file region (hp)"); 170 } 171 172 } 173 } 174 } 175 } 176 177 class HelloApp { 178 public static void main(String args[]) { 179 System.out.println("Hello Leyden"); 180 } 181 }