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=8000 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 }