1 /* 2 * Copyright (c) 2020, 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 & !vm.graal.enabled 28 * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds 29 * @run driver OptimizeModuleHandlingTest 30 * @summary test module path changes for optimization of 31 * module handling. 32 * 33 */ 34 35 import java.io.File; 36 import java.nio.file.Files; 37 import java.nio.file.Path; 38 import java.nio.file.Paths; 39 40 import jdk.test.lib.process.OutputAnalyzer; 41 42 public class OptimizeModuleHandlingTest { 43 44 private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); 45 46 private static final String TEST_SRC = System.getProperty("test.src"); 47 48 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 49 private static final Path MODS_DIR = Paths.get("mody"); 50 51 // the module name of the test module 52 private static final String MAIN_MODULE = "com.bars"; 53 private static final String TEST_MODULE = "com.foos"; 54 55 // the module main class 56 private static final String MAIN_CLASS = "com.bars.Main"; 57 private static final String TEST_CLASS = "com.foos.Test"; 58 59 private static String PATH_LIBS = "modylibs"; 60 private static Path libsDir = null; 61 private static Path mainJar = null; 62 private static Path testJar = null; 63 64 private static String CLASS_FOUND_MESSAGE = "com.foos.Test found"; 65 private static String CLASS_NOT_FOUND_MESSAGE = "java.lang.ClassNotFoundException: com.foos.Test"; 66 private static String OPTIMIZE_ENABLED = "optimized module handling: enabled"; 67 private static String OPTIMIZE_DISABLED = "optimized module handling: disabled"; 68 private static String MAIN_FROM_JAR = "class,load.*com.bars.Main.*[.]jar"; 69 private static String MAIN_FROM_CDS = "class,load.*com.bars.Main.*shared objects file"; 70 private static String TEST_FROM_JAR = "class,load.*com.foos.Test.*[.]jar"; 71 private static String TEST_FROM_CDS = "class,load.*com.foos.Test.*shared objects file"; 72 private static String MAP_FAILED = "Unable to use shared archive"; 73 private static String PATH_SEPARATOR = File.pathSeparator; 74 75 public static void buildTestModule() throws Exception { 76 77 // javac -d mods/$TESTMODULE src/$TESTMODULE/** 78 JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE), 79 MODS_DIR.resolve(TEST_MODULE), 80 null); 81 82 // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** 83 JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE), 84 MODS_DIR.resolve(MAIN_MODULE), 85 MODS_DIR.toString()); 86 87 libsDir = Files.createTempDirectory(USER_DIR, PATH_LIBS); 88 mainJar = libsDir.resolve(MAIN_MODULE + ".jar"); 89 testJar = libsDir.resolve(TEST_MODULE + ".jar"); 90 91 // modylibs contains both modules com.foos.jar, com.bars.jar 92 // build com.foos.jar 93 String classes = MODS_DIR.resolve(TEST_MODULE).toString(); 94 JarBuilder.createModularJar(testJar.toString(), classes, TEST_CLASS); 95 96 // build com.bars.jar 97 classes = MODS_DIR.resolve(MAIN_MODULE).toString(); 98 JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS); 99 } 100 101 public static void main(String... args) throws Exception { 102 runWithModulePath(); 103 runWithJarPath(); 104 } 105 106 private static void tty(String... args) { 107 for (String s : args) { 108 System.out.print(s + " "); 109 } 110 System.out.print("\n"); 111 } 112 113 public static void runWithModulePath(String... extraRuntimeArgs) throws Exception { 114 // compile the modules and create the modular jar files 115 buildTestModule(); 116 String appClasses[] = {MAIN_CLASS, TEST_CLASS}; 117 // create an archive with the classes in the modules built in the 118 // previous step 119 OutputAnalyzer output = TestCommon.createArchive( 120 null, appClasses, 121 "--module-path", 122 libsDir.toString(), 123 "-m", MAIN_MODULE); 124 TestCommon.checkDump(output); 125 126 // following 1 - 4 test with CDS off 127 tty("1. run with CDS off"); 128 TestCommon.execOff( "-p", libsDir.toString(), 129 "-m", MAIN_MODULE) 130 .shouldHaveExitValue(0) 131 .shouldNotContain(OPTIMIZE_ENABLED) 132 .shouldContain(CLASS_FOUND_MESSAGE); 133 tty("2. run with CDS off, without module path"); 134 TestCommon.execOff("-cp", 135 mainJar.toString(), 136 MAIN_CLASS) 137 .shouldHaveExitValue(0) 138 .shouldContain(CLASS_NOT_FOUND_MESSAGE); 139 tty("3. run with CDS off, but with full jars in path"); 140 TestCommon.execOff( "-cp", mainJar.toString() + PATH_SEPARATOR + testJar.toString(), 141 MAIN_CLASS) 142 .shouldHaveExitValue(0) 143 .shouldNotContain(OPTIMIZE_ENABLED) 144 .shouldContain(CLASS_FOUND_MESSAGE); 145 tty("4. run with CDS off, only main jar on path, but given moudle path"); 146 TestCommon.execOff( "-cp", mainJar.toString(), 147 "--module-path", libsDir.toString(), 148 "--add-modules", TEST_MODULE, 149 MAIN_CLASS) 150 .shouldHaveExitValue(0) 151 .shouldNotContain(OPTIMIZE_ENABLED) 152 .shouldContain(CLASS_FOUND_MESSAGE); 153 154 // Following 5 - 10 test with CDS on 155 tty("5. run with CDS on, with module path"); 156 String prefix[] = {"-Djava.class.path=", "-Xlog:cds", "-Xlog:class+load"}; 157 TestCommon.runWithModules(prefix, 158 null, // --upgrade-module-path 159 libsDir.toString(), // --module-path 160 MAIN_MODULE) // -m 161 .assertNormalExit(out -> { 162 out.shouldNotContain(OPTIMIZE_ENABLED) 163 .shouldContain(OPTIMIZE_DISABLED) 164 .shouldMatch(MAIN_FROM_CDS) // // archived Main class is for module only 165 .shouldContain(CLASS_FOUND_MESSAGE); 166 }); 167 tty("6. run with CDS on, with module paths set correctly"); 168 TestCommon.run("-Xlog:cds", 169 "-Xlog:class+load", 170 "-p", libsDir.toString(), 171 "-m", MAIN_MODULE) 172 .assertNormalExit(out -> { 173 out.shouldContain(CLASS_FOUND_MESSAGE) 174 .shouldMatch(MAIN_FROM_CDS) 175 .shouldMatch(TEST_FROM_CDS) 176 .shouldContain(OPTIMIZE_DISABLED) 177 .shouldNotContain(OPTIMIZE_ENABLED); 178 }); 179 tty("7. run with CDS on, with jar on path"); 180 TestCommon.run("-Xlog:cds", 181 "-Xlog:class+load", 182 "-cp", mainJar.toString() + PATH_SEPARATOR + testJar.toString(), 183 MAIN_CLASS) 184 .assertNormalExit(out -> { 185 out.shouldContain(CLASS_FOUND_MESSAGE) 186 .shouldMatch(MAIN_FROM_JAR) 187 .shouldMatch(TEST_FROM_JAR) 188 .shouldContain(OPTIMIZE_DISABLED) 189 .shouldNotContain(OPTIMIZE_ENABLED); 190 }); 191 192 tty("8. run with CDS on, with --module-path, with jar should fail"); 193 TestCommon.run("-Xlog:cds", 194 "-Xlog:class+load", 195 "-p", libsDir.toString(), 196 "-cp", mainJar.toString(), 197 MAIN_CLASS) 198 .assertNormalExit(out -> { 199 out.shouldContain(CLASS_NOT_FOUND_MESSAGE) 200 .shouldMatch(MAIN_FROM_JAR) 201 .shouldNotContain(OPTIMIZE_ENABLED); 202 }); 203 tty("9. run with CDS on, with com.foos on --module-path, with main jar on cp should pass"); 204 TestCommon.run("-Xlog:cds", 205 "-Xlog:class+load", 206 "--module-path", libsDir.toString(), 207 "--add-modules", TEST_MODULE, 208 "-cp", mainJar.toString(), 209 MAIN_CLASS) 210 .assertNormalExit(out -> { 211 out.shouldContain(CLASS_FOUND_MESSAGE) 212 .shouldMatch(MAIN_FROM_JAR) 213 .shouldMatch(TEST_FROM_CDS) 214 .shouldNotContain(OPTIMIZE_ENABLED); 215 }); 216 tty("10. run with CDS on, --module-path, with -Xbootclasspath/a: ."); 217 TestCommon.run("-Xlog:cds", 218 "-Xbootclasspath/a:", ".", 219 "--module-path", libsDir.toString(), 220 MAIN_CLASS) 221 .assertAbnormalExit(out -> { 222 out.shouldNotContain(CLASS_FOUND_MESSAGE) 223 .shouldContain(OPTIMIZE_DISABLED) // mapping info 224 .shouldContain("shared class paths mismatch"); 225 }); 226 } 227 228 public static void runWithJarPath(String... extraRuntimeArgs) throws Exception { 229 // compile the modules and create the modular jar files 230 buildTestModule(); 231 String appClasses[] = {MAIN_CLASS, TEST_CLASS}; 232 // create an archive with the classes in the modules built in the 233 // previous step 234 OutputAnalyzer output = TestCommon.createArchive( 235 testJar.toString() + PATH_SEPARATOR + mainJar.toString(), 236 appClasses); 237 TestCommon.checkDump(output); 238 239 // tests 1 - 4 test with CDS off are same as with module archive. 240 tty("tests 1 - 4 test with CDS off are same as with module archive, skipped"); 241 242 // Following 5 - 9 test with CDS on 243 tty("5. run with CDS on, with module path"); 244 String prefix[] = {"-Djava.class.path=", "-Xlog:cds"}; 245 TestCommon.runWithModules(prefix, 246 null, // --upgrade-module-path 247 libsDir.toString(), // --module-path 248 MAIN_MODULE) // -m 249 .assertAbnormalExit(out -> { 250 out.shouldContain(MAP_FAILED) 251 .shouldNotContain(OPTIMIZE_ENABLED) 252 .shouldNotContain(CLASS_FOUND_MESSAGE); 253 }); 254 tty("6. run with CDS on, with module paths set correctly"); 255 TestCommon.run("-Xlog:cds", 256 "-p", libsDir.toString(), 257 "-m", MAIN_MODULE) 258 .assertAbnormalExit(out -> { 259 out.shouldContain(MAP_FAILED) 260 .shouldNotContain(CLASS_FOUND_MESSAGE) 261 .shouldNotContain(OPTIMIZE_ENABLED); 262 }); 263 tty("7. run with CDS on, with jar on path"); 264 TestCommon.run("-Xlog:cds", 265 "-Xlog:class+load", 266 "-cp", testJar.toString() + PATH_SEPARATOR + mainJar.toString(), 267 MAIN_CLASS) 268 .assertNormalExit(out -> { 269 out.shouldMatch(MAIN_FROM_CDS) 270 .shouldMatch(TEST_FROM_CDS) 271 .shouldContain(CLASS_FOUND_MESSAGE) 272 .shouldContain(OPTIMIZE_ENABLED); 273 }); 274 tty("8. run with CDS on, with --module-path, with jars on classpath should run but not optimized"); 275 TestCommon.run("-Xlog:cds", 276 "-Xlog:class+load", 277 "-p", libsDir.toString(), 278 "-cp", testJar.toString() + PATH_SEPARATOR + mainJar.toString(), 279 "--add-modules=com.bars", // Main/Test from jars 280 MAIN_CLASS) 281 .assertNormalExit(out -> { 282 out.shouldMatch(MAIN_FROM_JAR) 283 .shouldMatch(TEST_FROM_JAR) 284 .shouldContain(CLASS_FOUND_MESSAGE) 285 .shouldNotContain(OPTIMIZE_ENABLED); 286 }); 287 tty("9. run with CDS on, with main jar only on classpath should not pass"); 288 TestCommon.run("-Xlog:cds", 289 "-cp", mainJar.toString(), 290 MAIN_CLASS) 291 .assertAbnormalExit(out -> { 292 out.shouldContain(MAP_FAILED) 293 .shouldNotContain(CLASS_FOUND_MESSAGE) 294 .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) 295 .shouldNotContain(OPTIMIZE_ENABLED) 296 .shouldNotContain(OPTIMIZE_DISABLED); 297 }); 298 tty("10. run with CDS on, with main/test jars on classpath also with -Xbootclasspath/a: should not pass"); 299 TestCommon.run("-Xlog:cds", 300 "-cp", mainJar.toString() + PATH_SEPARATOR + testJar.toString(), 301 "-Xbootclasspath/a:", ".", 302 MAIN_CLASS) 303 .assertAbnormalExit(out -> { 304 out.shouldNotContain(CLASS_FOUND_MESSAGE) 305 .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) 306 .shouldContain(OPTIMIZE_DISABLED) 307 .shouldNotContain(OPTIMIZE_ENABLED) 308 .shouldContain(MAP_FAILED); 309 }); 310 } 311 }