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 }