1 /**
   2  * Copyright (c) 2018, 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  * @test
  26  * @summary Test archived module graph with custom runtime image
  27  * @requires vm.cds.archived.java.heap
  28  * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
  29  * @modules java.base/jdk.internal.module
  30  *          java.management
  31  *          jdk.jlink
  32  *          jdk.compiler
  33  * @build sun.hotspot.WhiteBox
  34  * @compile CheckArchivedModuleApp.java
  35  * @run driver ClassFileInstaller -jar app.jar CheckArchivedModuleApp
  36  * @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
  37  * @run main ArchivedModuleWithCustomImageTest
  38  */
  39 
  40 import java.io.File;
  41 import java.nio.file.Files;
  42 import java.nio.file.Path;
  43 import java.nio.file.Paths;
  44 
  45 import jdk.test.lib.compiler.CompilerUtils;
  46 import jdk.test.lib.process.OutputAnalyzer;
  47 import jdk.test.lib.process.ProcessTools;
  48 
  49 public class ArchivedModuleWithCustomImageTest {
  50     private static final String JAVA_HOME = System.getProperty("java.home");
  51     private static final String TEST_MODULE = "test";
  52     private static final Path jdkHome = Paths.get(System.getProperty("test.jdk"));
  53     private static final Path jdkMods = jdkHome.resolve("jmods");
  54     private static final Path testSrc = Paths.get(System.getProperty("test.src"));
  55     private static final Path src = testSrc.resolve("src").resolve(TEST_MODULE);
  56     private static final Path classes = Paths.get("classes");
  57     private static final Path jmods = Paths.get("jmods");
  58 
  59     public static void main(String[] args) throws Throwable {
  60         if (Files.notExists(jdkMods)) {
  61             System.out.println("No jmods/ in test JDK, not supported.");
  62             return;
  63         }
  64 
  65         // compile test module class
  66         if (!CompilerUtils.compile(src, classes)) {
  67             throw new RuntimeException("Compilation failure.");
  68         }
  69 
  70         // create custom runtime image named 'myimage'
  71         Files.createDirectories(jmods);
  72         Path image = Paths.get("myimage");
  73         runJmod(classes.toString(), TEST_MODULE);
  74         runJlink(image, TEST_MODULE);
  75 
  76         // test using 'myimage'
  77         testArchivedModuleUsingImage(image);
  78 
  79         Files.delete(jmods.resolve(TEST_MODULE + ".jmod"));
  80     }
  81 
  82     private static void runJlink(Path image, String modName) throws Throwable {
  83         Path jlink = Paths.get(JAVA_HOME, "bin", "jlink");
  84         OutputAnalyzer output = ProcessTools.executeProcess(jlink.toString(),
  85                         "--output", image.toString(),
  86                         "--add-modules", modName,
  87                         "--module-path", jdkMods + File.pathSeparator + jmods);
  88         output.shouldHaveExitValue(0);
  89     }
  90 
  91     private static void runJmod(String cp, String modName) throws Throwable {
  92         Path jmod = Paths.get(JAVA_HOME, "bin", "jmod");
  93         OutputAnalyzer output = ProcessTools.executeProcess(jmod.toString(),
  94                        "create",
  95                        "--class-path", cp,
  96                        "--module-version", "1.0",
  97                        "--main-class", "jdk.test.Test",
  98                        jmods.resolve(modName + ".jmod").toString());
  99         output.shouldHaveExitValue(0);
 100     }
 101 
 102     private static void testArchivedModuleUsingImage(Path image)
 103                             throws Throwable {
 104         String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
 105         String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
 106         String appJar = ClassFileInstaller.getJarPath("app.jar");
 107         Path customJava = Paths.get(image.toString(), "bin", "java");
 108 
 109         // -Xshare:dump with custom runtime image
 110         String[] dumpCmd = {
 111             customJava.toString(),
 112             "-XX:SharedArchiveFile=./ArchivedModuleWithCustomImageTest.jsa",
 113             "-Xshare:dump"};
 114         printCommand(dumpCmd);
 115         ProcessBuilder pbDump = new ProcessBuilder();
 116         pbDump.command(dumpCmd);
 117         OutputAnalyzer output = TestCommon.executeAndLog(
 118             pbDump, "custom.runtime.image.dump");
 119         TestCommon.checkDump(output);
 120 
 121         // Test case 1):
 122         // test archived module graph objects are used with custome runtime image
 123         System.out.println("------------------- Test case 1 -------------------");
 124         String[] runCmd = {customJava.toString(),
 125                            use_whitebox_jar,
 126                            "-XX:SharedArchiveFile=./ArchivedModuleWithCustomImageTest.jsa",
 127                            "-cp",
 128                            appJar,
 129                            "-Xshare:on",
 130                            "-XX:+UnlockDiagnosticVMOptions",
 131                            "-XX:+WhiteBoxAPI",
 132                            "CheckArchivedModuleApp",
 133                            "yes"};
 134         printCommand(runCmd);
 135         ProcessBuilder pbRun = new ProcessBuilder();
 136         pbRun.command(runCmd);
 137         output = TestCommon.executeAndLog(pbRun, "custom.runtime.image.run");
 138         output.shouldHaveExitValue(0);
 139 
 140 
 141         // Test case 2):
 142         // verify --show-module-resolution output
 143         System.out.println("------------------- Test case 2 -------------------");
 144 
 145         // myimage/bin/java -Xshare:off --show-module-resolution -version
 146         String[] showModuleCmd1 = {customJava.toString(),
 147                                    "-Xshare:off",
 148                                    "--show-module-resolution",
 149                                    "-version"};
 150         printCommand(showModuleCmd1);
 151         pbRun = new ProcessBuilder();
 152         pbRun.command(showModuleCmd1);
 153         output = TestCommon.executeAndLog(
 154             pbRun, "custom.runtime.image.showModuleResolution.nocds");
 155         output.shouldHaveExitValue(0);
 156         String moduleResolutionOut1 = output.getStdout();
 157 
 158         // myimage/bin/java -Xshare:on --show-module-resolution -version
 159         //    -XX:SharedArchiveFile=./ArchivedModuleWithCustomImageTest.jsa
 160         String[] showModuleCmd2 = {
 161             customJava.toString(),
 162             "-XX:SharedArchiveFile=./ArchivedModuleWithCustomImageTest.jsa",
 163             "-Xshare:on",
 164             "--show-module-resolution",
 165             "-version"};
 166         printCommand(showModuleCmd2);
 167         pbRun = new ProcessBuilder();
 168         pbRun.command(showModuleCmd2);
 169         output = TestCommon.executeAndLog(
 170             pbRun, "custom.runtime.image.showModuleResolution.cds");
 171         if (output.getStderr().contains("sharing")) {
 172             String moduleResolutionOut2 = output.getStdout();
 173             TestCommon.checkOutputStrings(
 174                 moduleResolutionOut1, moduleResolutionOut2, "\n");
 175         }
 176     }
 177 
 178     private static void printCommand(String opts[]) {
 179         StringBuilder cmdLine = new StringBuilder();
 180         for (String cmd : opts)
 181             cmdLine.append(cmd).append(' ');
 182         System.out.println("Command line: [" + cmdLine.toString() + "]");
 183     }
 184 }