1 /* 2 * Copyright Amazon.com Inc. 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 import java.util.ArrayList; 26 import java.util.List; 27 import java.nio.file.Path; 28 import java.nio.file.Paths; 29 import java.nio.file.Files; 30 31 import jdk.test.lib.cds.CDSJarUtils; 32 import jdk.test.lib.cds.CDSTestUtils; 33 import jdk.test.lib.process.OutputAnalyzer; 34 35 /* 36 * @test 37 * @summary Try to archive lots and lots of classes. 38 * @requires vm.cds 39 * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds 40 * @run driver/timeout=500 LotsOfSyntheticClasses 41 */ 42 43 public class LotsOfSyntheticClasses { 44 45 // Generate 70 top-level classes, each containing 1000 nested classes. 46 // 70K total classes is enough to push the CDS limits. Any archived 47 // collection that holds Classes should not have backing storage larger 48 // than CDS archival limit (256KB). This means we want at least 64K classes 49 // to probe that limit. 50 private static final int NUM_CLASSES = 70; 51 private static final int NUM_NESTED_CLASSES = 1000; 52 53 private static final Path USER_DIR = Paths.get(CDSTestUtils.getOutputDir()); 54 private static final Path APP_JAR = USER_DIR.resolve("test.jar"); 55 private static final Path SRC_DIR = USER_DIR.resolve("src"); 56 57 private static final String TOP_CLASS_NAME = "Class"; 58 private static final String NESTED_CLASS_NAME = "Nested"; 59 private static final String MAIN_CLASS_NAME = "Main"; 60 61 public static List<String> generateClass(int idx) { 62 List<String> out = new ArrayList<>(); 63 out.add("public class " + TOP_CLASS_NAME + idx + " {"); 64 out.add("public " + TOP_CLASS_NAME + idx + "() {"); 65 for (int c = 0; c < NUM_NESTED_CLASSES; c++) { 66 out.add("new " + NESTED_CLASS_NAME + c + "();"); 67 } 68 out.add("}"); 69 for (int c = 0; c < NUM_NESTED_CLASSES; c++) { 70 out.add("public static class " + NESTED_CLASS_NAME + c + " {}"); 71 } 72 out.add("}"); 73 return out; 74 } 75 76 public static List<String> generateMainClass() { 77 List<String> out = new ArrayList<>(); 78 out.add("public class " + MAIN_CLASS_NAME + " {"); 79 out.add("public static void main(String... args) {"); 80 for (int c = 0; c < NUM_CLASSES; c++) { 81 out.add("new " + TOP_CLASS_NAME + c + "();"); 82 } 83 out.add("System.out.println(\"Success\");"); 84 out.add("}"); 85 out.add("}"); 86 return out; 87 } 88 89 public static String[] listAppClasses() { 90 String[] res = new String[NUM_CLASSES * NUM_NESTED_CLASSES]; 91 for (int c = 0; c < NUM_CLASSES; c++) { 92 for (int sc = 0; sc < NUM_NESTED_CLASSES; sc++) { 93 res[c * NUM_NESTED_CLASSES + sc] = TOP_CLASS_NAME + c + "$" + NESTED_CLASS_NAME + sc; 94 } 95 } 96 return res; 97 } 98 99 public static void main(String[] args) throws Exception { 100 // Step 1. Generate classes and build the JAR with them. 101 { 102 SRC_DIR.toFile().mkdirs(); 103 104 for (int i = 0; i < NUM_CLASSES; i++) { 105 Path file = SRC_DIR.resolve(TOP_CLASS_NAME + i + ".java"); 106 Files.write(file, generateClass(i)); 107 } 108 109 Path mainFile = SRC_DIR.resolve(MAIN_CLASS_NAME + ".java"); 110 Files.write(mainFile, generateMainClass()); 111 112 CDSJarUtils.buildFromSourceDirectory( 113 APP_JAR.toString(), 114 SRC_DIR.toString() 115 ); 116 } 117 118 // Step 2. Try to dump the archive. 119 { 120 OutputAnalyzer output = TestCommon.createArchive( 121 APP_JAR.toString(), 122 listAppClasses(), 123 // Verification for lots of classes slows down the test. 124 "-XX:+IgnoreUnrecognizedVMOptions", 125 "-XX:+UnlockDiagnosticVMOptions", 126 "-XX:-ArchiveLoaderLookupCache", // LEYDEN_ONLY - work around JDK-8365959 127 "-XX:-VerifyDependencies", 128 "-XX:-VerifyBeforeExit" 129 ); 130 TestCommon.checkDump(output); 131 } 132 133 // Step 3. Try to run, touching every class. 134 { 135 TestCommon.run( 136 // Verification for lots of classes slows down the test. 137 "-XX:+IgnoreUnrecognizedVMOptions", 138 "-XX:+UnlockDiagnosticVMOptions", 139 "-XX:-VerifyDependencies", 140 "-XX:-VerifyBeforeExit", 141 "-cp", APP_JAR.toString(), 142 MAIN_CLASS_NAME). 143 assertNormalExit("Success"); 144 } 145 146 } 147 }