1 /* 2 * Copyright (c) 2014, 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 /* 26 * @test 27 * @summary Testing use of UseAppCDS flag 28 * @requires vm.cds 29 * @library /test/lib 30 * @modules java.base/jdk.internal.misc 31 * java.management 32 * jdk.jartool/sun.tools.jar 33 * @build UseAppCDS_Test 34 * @run main UseAppCDS 35 */ 36 37 import jdk.test.lib.JDKToolLauncher; 38 import jdk.test.lib.cds.CDSTestUtils; 39 import jdk.test.lib.process.OutputAnalyzer; 40 import jdk.test.lib.process.ProcessTools; 41 42 import java.util.ArrayList; 43 import java.util.List; 44 import java.io.*; 45 46 public class UseAppCDS { 47 48 // Class UseAppCDS_Test is loaded by the App loader 49 50 static final String TEST_OUT = "UseAppCDS_Test.main--executed"; 51 52 private static final String TESTJAR = "./test.jar"; 53 private static final String TESTNAME = "UseAppCDS_Test"; 54 private static final String TESTCLASS = TESTNAME + ".class"; 55 56 private static final String CLASSES_DIR = System.getProperty("test.classes", "."); 57 private static final String CLASSLIST_FILE = "./UseAppCDS.classlist"; 58 private static final String ARCHIVE_FILE = "./shared.jsa"; 59 private static final String BOOTCLASS = "java.lang.Class"; 60 61 public static void main(String[] args) throws Exception { 62 63 // First create a jar file for the application "test" class 64 JDKToolLauncher jar = JDKToolLauncher.create("jar") 65 .addToolArg("-cf") 66 .addToolArg(TESTJAR) 67 .addToolArg("-C") 68 .addToolArg(CLASSES_DIR) 69 .addToolArg(TESTCLASS); 70 71 ProcessBuilder pb = new ProcessBuilder(jar.getCommand()); 72 TestCommon.executeAndLog(pb, "jar01").shouldHaveExitValue(0); 73 74 pb = new ProcessBuilder(jar.getCommand()); 75 TestCommon.executeAndLog(pb, "jar02").shouldHaveExitValue(0); 76 77 // In all tests the BOOTCLASS should be loaded/dumped/used 78 79 // Test 1: No AppCDS - dumping loaded classes excludes the "test" classes 80 dumpLoadedClasses(false, new String[] { BOOTCLASS }, 81 new String[] { TESTNAME }); 82 83 // Test 2: AppCDS - dumping loaded classes includes "test" classes 84 dumpLoadedClasses(true, new String[] { BOOTCLASS, TESTNAME }, 85 new String[0]); 86 87 // Next tests rely on the classlist we just dumped 88 89 // Test 3: No AppCDS - "test" classes in classlist ignored when dumping 90 dumpArchive(false, new String[] { BOOTCLASS }, 91 new String[] { TESTNAME}); 92 93 // Test 4: AppCDS - "test" classes in classlist are dumped 94 dumpArchive(true, new String[] { BOOTCLASS, TESTNAME }, 95 new String[0]); 96 97 // Next tests rely on the archive we just dumped 98 99 // Test 5: No AppCDS - Using archive containing "test" classes ignores them 100 useArchive(false, new String[] { BOOTCLASS }, 101 new String[] { TESTNAME }); 102 103 // Test 6: AppCDS - Using archive containing "test" classes loads them 104 useArchive(true, new String[] { BOOTCLASS, TESTNAME }, 105 new String[0]); 106 } 107 108 public static List<String> toClassNames(String filename) throws IOException { 109 ArrayList<String> classes = new ArrayList<>(); 110 try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)))) { 111 for (; ; ) { 112 String line = br.readLine(); 113 if (line == null) { 114 break; 115 } 116 classes.add(line.replaceAll("/", ".")); 117 } 118 } 119 return classes; 120 } 121 122 static void dumpLoadedClasses(boolean useAppCDS, String[] expectedClasses, 123 String[] unexpectedClasses) throws Exception { 124 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 125 TestCommon.makeCommandLineForAppCDS( 126 "-XX:DumpLoadedClassList=" + CLASSLIST_FILE, 127 "-cp", 128 TESTJAR, 129 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 130 TESTNAME, 131 TEST_OUT)); 132 133 OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-loaded-classes") 134 .shouldHaveExitValue(0).shouldContain(TEST_OUT); 135 136 List<String> dumpedClasses = toClassNames(CLASSLIST_FILE); 137 138 for (String clazz : expectedClasses) { 139 if (!dumpedClasses.contains(clazz)) { 140 throw new RuntimeException(clazz + " missing in " + 141 CLASSLIST_FILE); 142 } 143 } 144 for (String clazz : unexpectedClasses) { 145 if (dumpedClasses.contains(clazz)) { 146 throw new RuntimeException("Unexpectedly found " + clazz + 147 " in " + CLASSLIST_FILE); 148 } 149 } 150 } 151 152 static void dumpArchive(boolean useAppCDS, String[] expectedClasses, 153 String[] unexpectedClasses) throws Exception { 154 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 155 TestCommon.makeCommandLineForAppCDS( 156 useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" : 157 "-XX:+UnlockDiagnosticVMOptions", 158 "-cp", 159 TESTJAR, 160 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 161 "-XX:SharedClassListFile=" + CLASSLIST_FILE, 162 "-XX:SharedArchiveFile=" + ARCHIVE_FILE, 163 "-Xlog:cds", 164 "-Xshare:dump")); 165 166 OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-archive") 167 .shouldHaveExitValue(0); 168 169 for (String clazz : expectedClasses) { 170 String failed = "Preload Warning: Cannot find " + clazz; 171 output.shouldNotContain(failed); 172 } 173 for (String clazz : unexpectedClasses) { 174 String failed = "Preload Warning: Cannot find " + clazz; 175 output.shouldContain(failed); 176 } 177 } 178 179 static void useArchive(boolean useAppCDS, String[] expectedClasses, 180 String[] unexpectedClasses) throws Exception { 181 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 182 TestCommon.makeCommandLineForAppCDS( 183 useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" : 184 "-XX:+UnlockDiagnosticVMOptions", 185 "-cp", 186 TESTJAR, 187 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 188 "-XX:SharedArchiveFile=" + ARCHIVE_FILE, 189 "-verbose:class", 190 "-Xshare:on", 191 TESTNAME, 192 TEST_OUT)); 193 194 OutputAnalyzer output = TestCommon.executeAndLog(pb, "use-archive"); 195 if (CDSTestUtils.isUnableToMap(output)) 196 System.out.println("Unable to map: test case skipped"); 197 else 198 output.shouldHaveExitValue(0).shouldContain(TEST_OUT); 199 200 // Quote the class name in the regex as it may contain $ 201 String prefix = ".class,load. "; 202 String archive_suffix = ".*source: shared objects file.*"; 203 String jar_suffix = ".*source: .*\\.jar"; 204 205 for (String clazz : expectedClasses) { 206 String pattern = prefix + clazz + archive_suffix; 207 try { 208 output.shouldMatch(pattern); 209 } catch (Exception e) { 210 TestCommon.checkCommonExecExceptions(output, e); 211 } 212 } 213 214 for (String clazz : unexpectedClasses) { 215 String pattern = prefix + clazz + archive_suffix; 216 try { 217 output.shouldNotMatch(pattern); 218 } catch (Exception e) { 219 TestCommon.checkCommonExecExceptions(output, e); 220 } 221 pattern = prefix + clazz + jar_suffix; 222 try { 223 output.shouldMatch(pattern); 224 } catch (Exception e) { 225 TestCommon.checkCommonExecExceptions(output, e); 226 } 227 } 228 } 229 }