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 // Although AppCDS isn't used, all classes will be found during dumping 91 // after the fix for JDK-8193434. Classes which are not in the boot 92 // loader dictionary will not be saved into the archive. 93 dumpArchive(false, new String[] { BOOTCLASS }, 94 new String[0]); 95 96 // Test 4: AppCDS - "test" classes in classlist are dumped 97 dumpArchive(true, new String[] { BOOTCLASS, TESTNAME }, 98 new String[0]); 99 100 // Next tests rely on the archive we just dumped 101 102 // Test 5: No AppCDS - Using archive containing "test" classes ignores them 103 useArchive(false, new String[] { BOOTCLASS }, 104 new String[] { TESTNAME }); 105 106 // Test 6: AppCDS - Using archive containing "test" classes loads them 107 useArchive(true, new String[] { BOOTCLASS, TESTNAME }, 108 new String[0]); 109 } 110 111 public static List<String> toClassNames(String filename) throws IOException { 112 ArrayList<String> classes = new ArrayList<>(); 113 try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)))) { 114 for (; ; ) { 115 String line = br.readLine(); 116 if (line == null) { 117 break; 118 } 119 classes.add(line.replaceAll("/", ".")); 120 } 121 } 122 return classes; 123 } 124 125 static void dumpLoadedClasses(boolean useAppCDS, String[] expectedClasses, 126 String[] unexpectedClasses) throws Exception { 127 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 128 TestCommon.makeCommandLineForAppCDS( 129 "-XX:DumpLoadedClassList=" + CLASSLIST_FILE, 130 "-cp", 131 TESTJAR, 132 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 133 TESTNAME, 134 TEST_OUT)); 135 136 OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-loaded-classes") 137 .shouldHaveExitValue(0).shouldContain(TEST_OUT); 138 139 List<String> dumpedClasses = toClassNames(CLASSLIST_FILE); 140 141 for (String clazz : expectedClasses) { 142 if (!dumpedClasses.contains(clazz)) { 143 throw new RuntimeException(clazz + " missing in " + 144 CLASSLIST_FILE); 145 } 146 } 147 for (String clazz : unexpectedClasses) { 148 if (dumpedClasses.contains(clazz)) { 149 throw new RuntimeException("Unexpectedly found " + clazz + 150 " in " + CLASSLIST_FILE); 151 } 152 } 153 } 154 155 static void dumpArchive(boolean useAppCDS, String[] expectedClasses, 156 String[] unexpectedClasses) throws Exception { 157 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 158 TestCommon.makeCommandLineForAppCDS( 159 useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" : 160 "-XX:+UnlockDiagnosticVMOptions", 161 "-cp", 162 TESTJAR, 163 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 164 "-XX:SharedClassListFile=" + CLASSLIST_FILE, 165 "-XX:SharedArchiveFile=" + ARCHIVE_FILE, 166 "-Xlog:cds", 167 "-Xshare:dump")); 168 169 OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-archive") 170 .shouldHaveExitValue(0); 171 172 for (String clazz : expectedClasses) { 173 String failed = "Preload Warning: Cannot find " + clazz; 174 output.shouldNotContain(failed); 175 } 176 for (String clazz : unexpectedClasses) { 177 String failed = "Preload Warning: Cannot find " + clazz; 178 output.shouldContain(failed); 179 } 180 } 181 182 static void useArchive(boolean useAppCDS, String[] expectedClasses, 183 String[] unexpectedClasses) throws Exception { 184 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 185 TestCommon.makeCommandLineForAppCDS( 186 useAppCDS ? "-XX:-UnlockDiagnosticVMOptions" : 187 "-XX:+UnlockDiagnosticVMOptions", 188 "-cp", 189 TESTJAR, 190 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 191 "-XX:SharedArchiveFile=" + ARCHIVE_FILE, 192 "-verbose:class", 193 "-Xshare:on", 194 TESTNAME, 195 TEST_OUT)); 196 197 OutputAnalyzer output = TestCommon.executeAndLog(pb, "use-archive"); 198 if (CDSTestUtils.isUnableToMap(output)) 199 System.out.println("Unable to map: test case skipped"); 200 else 201 output.shouldHaveExitValue(0).shouldContain(TEST_OUT); 202 203 // Quote the class name in the regex as it may contain $ 204 String prefix = ".class,load. "; 205 String archive_suffix = ".*source: shared objects file.*"; 206 String jar_suffix = ".*source: .*\\.jar"; 207 | 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 and TESTNAME should be loaded/dumped/used 78 79 // Test 1: -XX:-UseAppCDS - No effect, dumping loaded classes includes "test" classes 80 dumpLoadedClasses(false, new String[] { BOOTCLASS, TESTNAME }, 81 new String[0]); 82 83 // Test 2: -XX:+UseAppCDS - 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: -XX:-UseAppCDS - No effect, "test" classes in classlist are dumped 90 dumpArchive(false, new String[] { BOOTCLASS, TESTNAME }, 91 new String[0]); 92 93 // Test 4: -XX:+UseAppCDS - "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: -XX:-UseAppCDS - No effect, using archive containing "test" loads them 100 useArchive(false, new String[] { BOOTCLASS, TESTNAME }, 101 new String[0]); 102 103 // Test 6: -XX:+UseAppCDS - 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 "-cp", 157 TESTJAR, 158 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 159 "-XX:SharedClassListFile=" + CLASSLIST_FILE, 160 "-XX:SharedArchiveFile=" + ARCHIVE_FILE, 161 "-Xlog:cds", 162 "-Xshare:dump")); 163 164 OutputAnalyzer output = TestCommon.executeAndLog(pb, "dump-archive") 165 .shouldHaveExitValue(0); 166 167 for (String clazz : expectedClasses) { 168 String failed = "Preload Warning: Cannot find " + clazz; 169 output.shouldNotContain(failed); 170 } 171 for (String clazz : unexpectedClasses) { 172 String failed = "Preload Warning: Cannot find " + clazz; 173 output.shouldContain(failed); 174 } 175 } 176 177 static void useArchive(boolean useAppCDS, String[] expectedClasses, 178 String[] unexpectedClasses) throws Exception { 179 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 180 TestCommon.makeCommandLineForAppCDS( 181 "-cp", 182 TESTJAR, 183 useAppCDS ? "-XX:+UseAppCDS" : "-XX:-UseAppCDS", 184 "-XX:SharedArchiveFile=" + ARCHIVE_FILE, 185 "-verbose:class", 186 "-Xshare:on", 187 TESTNAME, 188 TEST_OUT)); 189 190 OutputAnalyzer output = TestCommon.executeAndLog(pb, "use-archive"); 191 if (CDSTestUtils.isUnableToMap(output)) 192 System.out.println("Unable to map: test case skipped"); 193 else 194 output.shouldHaveExitValue(0).shouldContain(TEST_OUT); 195 196 // Quote the class name in the regex as it may contain $ 197 String prefix = ".class,load. "; 198 String archive_suffix = ".*source: shared objects file.*"; 199 String jar_suffix = ".*source: .*\\.jar"; 200 |