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