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 * @requires vm.cds 28 * @requires vm.cds.supports.aot.class.linking 29 * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds 30 * @run driver AddOpens 31 * @summary sanity test the --add-opens option 32 */ 33 34 import java.io.File; 35 import java.nio.file.Files; 36 import java.nio.file.Path; 37 import java.nio.file.Paths; 38 39 import jdk.test.lib.cds.CDSTestUtils; 40 import jdk.test.lib.cds.CDSAppTester; 41 import jdk.test.lib.cds.SimpleCDSAppTester; 42 import jdk.test.lib.process.OutputAnalyzer; 43 44 public class AddOpens { 45 private static final String SEP = File.separator; 46 47 private static final Path USER_DIR = Paths.get(CDSTestUtils.getOutputDir()); 48 49 private static final Path SRC_DIR = Paths.get(System.getProperty("test.src")). 50 resolve( ".." + SEP + "jigsaw" + SEP + "modulepath" + SEP + "src"); 51 52 private static final Path MODS_DIR = Paths.get("mods"); 53 54 // the module name of the test module 55 private static final String TEST_MODULE1 = "com.simple"; 56 57 // the module main class 58 private static final String MAIN_CLASS = "com.simple.Main"; 59 60 private static Path moduleDir = null; 61 private static Path moduleDir2 = null; 62 private static Path destJar = null; 63 64 private static String addOpensArg = "java.base/java.lang=" + TEST_MODULE1; 65 private static String addOpensAllUnnamed = "java.base/java.lang=ALL-UNNAMED"; 66 private static String extraOpts[][] = 67 {{"-Xlog:cds", "-Xlog:cds"}, 68 {"--add-opens", addOpensArg}}; 69 private static String expectedOutput[] = 70 { "[class,load] com.simple.Main source: shared objects file", 71 "method.setAccessible succeeded!"}; 72 73 public static void buildTestModule() throws Exception { 74 75 // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** 76 JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1), 77 MODS_DIR.resolve(TEST_MODULE1), 78 MODS_DIR.toString()); 79 80 moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); 81 moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2"); 82 83 Path srcJar = moduleDir.resolve(TEST_MODULE1 + ".jar"); 84 destJar = moduleDir2.resolve(TEST_MODULE1 + ".jar"); 85 String classes = MODS_DIR.resolve(TEST_MODULE1).toString(); 86 JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS); 87 Files.copy(srcJar, destJar); 88 89 } 90 91 static int testCount = 0; 92 static void printComment(String comment) { 93 testCount ++; 94 System.out.println("======================================================================"); 95 System.out.println("TESTCASE " + testCount + ": " + comment); 96 System.out.println("======================================================================"); 97 } 98 99 static SimpleCDSAppTester test(String comment, SimpleCDSAppTester tester) throws Exception { 100 printComment(comment); 101 return tester 102 .setAssemblyChecker((OutputAnalyzer out) -> { 103 out.shouldContain("Full module graph = enabled"); 104 }) 105 .setProductionChecker((OutputAnalyzer out) -> { 106 out.shouldContain(expectedOutput[0]); 107 out.shouldContain(expectedOutput[1]); 108 }) 109 .runStaticWorkflow() 110 .runAOTWorkflow(); 111 } 112 113 static class Tester1 extends CDSAppTester { 114 public Tester1(String testName) { 115 super(testName); 116 } 117 118 @Override 119 public String[] vmArgs(RunMode runMode) { 120 if (runMode == RunMode.DUMP_STATIC) { 121 return new String[] { "-Xlog:cds" }; 122 } else { 123 return new String[] { 124 "--add-opens", addOpensArg, "-Xlog:class+load=trace", 125 }; 126 } 127 } 128 129 @Override 130 public String classpath(RunMode runMode) { 131 return destJar.toString(); 132 } 133 134 @Override 135 public String modulepath(RunMode runMode) { 136 return moduleDir.toString(); 137 } 138 139 @Override 140 public String[] appCommandLine(RunMode runMode) { 141 if (runMode == RunMode.TRAINING || 142 runMode == RunMode.ASSEMBLY || 143 runMode == RunMode.DUMP_STATIC) { 144 return new String[] { 145 "-m", TEST_MODULE1, 146 }; 147 } else { 148 return new String[] { 149 "-m", TEST_MODULE1, "with_add_opens", 150 }; 151 } 152 } 153 154 @Override 155 public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception { 156 if (runMode == RunMode.PRODUCTION) { 157 out.shouldContain(expectedOutput[0]); 158 out.shouldContain(expectedOutput[1]); 159 } else if (runMode == RunMode.ASSEMBLY) { 160 out.shouldContain("full module graph: enabled"); 161 } 162 } 163 } 164 165 static class Tester2 extends CDSAppTester { 166 public Tester2(String testName) { 167 super(testName); 168 } 169 170 @Override 171 public String[] vmArgs(RunMode runMode) { 172 return new String[] { 173 "--add-opens", addOpensAllUnnamed, "-Xlog:class+load=trace", 174 }; 175 } 176 177 @Override 178 public String classpath(RunMode runMode) { 179 return destJar.toString(); 180 } 181 182 @Override 183 public String[] appCommandLine(RunMode runMode) { 184 if (runMode == RunMode.TRAINING || 185 runMode == RunMode.ASSEMBLY || 186 runMode == RunMode.DUMP_STATIC) { 187 return new String[] { 188 MAIN_CLASS, 189 }; 190 } else { 191 return new String[] { 192 MAIN_CLASS, "with_add_opens", 193 }; 194 } 195 } 196 197 @Override 198 public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception { 199 if (runMode == RunMode.PRODUCTION) { 200 out.shouldContain(expectedOutput[0]); 201 out.shouldContain(expectedOutput[1]); 202 } else if (runMode == RunMode.ASSEMBLY) { 203 out.shouldContain("full module graph: enabled"); 204 } 205 } 206 } 207 208 public static void main(String... args) throws Exception { 209 // compile the modules and create the modular jar files 210 buildTestModule(); 211 String appClasses[] = {MAIN_CLASS}; 212 OutputAnalyzer output; 213 214 test("Same --add-opens during ASSEMBLY/DUMP_STATIC and PRODUCTION RunMode", 215 SimpleCDSAppTester.of("same-add-opens") 216 .classpath(destJar.toString()) 217 .addVmArgs("--add-opens", addOpensArg, "-Xlog:class+load=trace") 218 .modulepath(moduleDir.toString()) 219 .appCommandLine("-m", TEST_MODULE1, "with_add_opens")); 220 221 printComment("no --add-opens during DUMP_STATIC RunMode; --add-opens during PRODUCTION RunMode"); 222 Tester1 t1 = new Tester1("no-add-opens-in-DUMP_STATIC"); 223 t1.run("AOT"); 224 t1.run("STATIC"); 225 226 printComment("--add-opens ALL-UNNAMED during ASSEMBLY/DUMP_STATIC and PRODUCTION RunMode"); 227 Tester2 t2 = new Tester2("add-opens-ALL-UNNAMED"); 228 t2.run("AOT"); 229 t2.run("STATIC"); 230 231 } 232 }