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