1 /*
  2  * Copyright (c) 2022, 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  * @summary Test -XX:+AutoCreateSharedArchive on a copied JDK without default shared archive
 28  * @bug 8261455
 29  * @requires vm.cds
 30  * @requires vm.flagless
 31  * @comment This test doesn't work on Windows because it depends on symlinks
 32  * @requires os.family != "windows"
 33  * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
 34  * @compile ../test-classes/Hello.java
 35  * @run driver TestAutoCreateSharedArchiveNoDefaultArchive
 36  */
 37 
 38 import java.io.File;
 39 import jdk.test.lib.cds.CDSTestUtils;
 40 import jdk.test.lib.process.OutputAnalyzer;
 41 
 42 public class TestAutoCreateSharedArchiveNoDefaultArchive {
 43     public static void main(String[] args) throws Exception {
 44         String mainClass = "Hello";
 45         String java_home_src = System.getProperty("java.home");
 46         String java_home_dst = CDSTestUtils.getOutputDir() + File.separator + "moved_jdk";
 47         CDSTestUtils.clone(new File(java_home_src), new File(java_home_dst));
 48         System.out.println("======== Cloned JDK at " + java_home_dst);
 49 
 50         String homeJava = java_home_src + File.separator + "bin" + File.separator + "java";
 51         String dstJava  = java_home_dst + File.separator + "bin" + File.separator + "java";
 52 
 53         TestCommon.startNewArchiveName();
 54         String jsaFileName = TestCommon.getCurrentArchiveName();
 55         File jsaFile = new File(jsaFileName);
 56         if (jsaFile.exists()) {
 57             jsaFile.delete();
 58         }
 59 
 60         String jsaOpt = "-XX:SharedArchiveFile=" + jsaFileName;
 61         String autoCreateArchive = "-XX:+AutoCreateSharedArchive";
 62         {
 63             ProcessBuilder pb = CDSTestUtils.makeBuilder(homeJava,
 64                                                          "-Xshare:dump",
 65                                                          jsaOpt);
 66             TestCommon.executeAndLog(pb, "dump")
 67                       .shouldHaveExitValue(0);
 68         }
 69         {
 70             ProcessBuilder pb = CDSTestUtils.makeBuilder(homeJava,
 71                                                          "-Xshare:auto",
 72                                                          jsaOpt,
 73                                                          "-Xlog:class+path=info",
 74                                                          "-version");
 75             OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-src");
 76             out.shouldHaveExitValue(0);
 77             out.shouldNotContain("shared class paths mismatch");
 78             out.shouldNotContain("BOOT classpath mismatch");
 79         }
 80 
 81         String helloJar = JarBuilder.getOrCreateHelloJar();
 82 
 83         if (jsaFile.exists()) {
 84             jsaFile.delete();
 85         }
 86         // Test runtime with cloned JDK
 87         System.out.println("======== run with cloned jdk to created dynamic shared archive at exit");
 88         {
 89             ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava,
 90                                                          "-Xshare:auto",
 91                                                          autoCreateArchive,
 92                                                          jsaOpt,
 93                                                          "-Xlog:cds",
 94                                                          "-Xlog:class+path=info",
 95                                                          "-cp", helloJar,
 96                                                          mainClass);
 97             OutputAnalyzer out = TestCommon.executeAndLog(pb, "exec-dst");
 98             out.shouldHaveExitValue(0);
 99             out.shouldContain("Dumping shared data to file");
100             if (!jsaFile.exists()) {
101                 throw new RuntimeException("Shared archive " + jsaFileName + " should be created at exit");
102             }
103         }
104 
105         // Remove all possible default archives
106         removeDefaultArchives(java_home_dst, "zero");
107         removeDefaultArchives(java_home_dst, "server");
108         removeDefaultArchives(java_home_dst, "client");
109         {
110             ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava,
111                                                          "-Xlog:cds",
112                                                          "-version");
113             TestCommon.executeAndLog(pb, "show-version")
114                       .shouldHaveExitValue(0)
115                       .shouldContain("Initialize static archive failed")
116                       .shouldContain("Unable to map shared spaces")
117                       .shouldNotContain("sharing");
118         }
119         // delete existing jsa file
120         if (jsaFile.exists()) {
121             jsaFile.delete();
122         }
123         System.out.println("======= run with no default shared archive should not create shared archive at exit");
124         {
125             ProcessBuilder pb = CDSTestUtils.makeBuilder(dstJava,
126                                                          "-Xshare:auto",
127                                                          autoCreateArchive,
128                                                          jsaOpt,
129                                                          "-Xlog:cds",
130                                                          "-Xlog:class+path=info",
131                                                          "-cp", helloJar,
132                                                          mainClass);
133             TestCommon.executeAndLog(pb, "no-default-archive")
134                       .shouldHaveExitValue(0)
135                       .shouldContain("Initialize static archive failed")
136                       .shouldContain("Unable to map shared spaces")
137                       .shouldNotContain("Dumping shared data to file");
138             if (jsaFile.exists()) {
139                 throw new RuntimeException("Archive file " + jsaFileName + " should not be created at exit");
140             }
141         }
142     }
143 
144     private static void removeDefaultArchives(String java_home_dst, String variant) {
145         removeDefaultArchive(java_home_dst, variant, "");
146         removeDefaultArchive(java_home_dst, variant, "_nocoops");
147     }
148 
149     private static void removeDefaultArchive(String java_home_dst, String variant, String suffix) {
150         String fileName = java_home_dst + File.separator + "lib" + File.separator + variant +
151                           File.separator +  "classes" + suffix + ".jsa";
152         File f = new File(fileName);
153         if (f.delete()) {
154             System.out.println("======= removed " + fileName);
155         }
156     }
157 }