|
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 * @test TestGCLogMessages |
|
26 * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 8076463 8150630 8160055 8177059 8166191 |
|
27 * @summary Ensure the output for a minor GC with G1 |
|
28 * includes the expected necessary messages. |
|
29 * @key gc |
|
30 * @requires vm.gc.G1 |
|
31 * @library /test/lib |
|
32 * @modules java.base/jdk.internal.misc |
|
33 * java.management |
|
34 * @build sun.hotspot.WhiteBox |
|
35 * @run main ClassFileInstaller sun.hotspot.WhiteBox |
|
36 * @run main TestGCLogMessages |
|
37 */ |
|
38 |
|
39 import jdk.test.lib.process.OutputAnalyzer; |
|
40 import jdk.test.lib.process.ProcessTools; |
|
41 import jdk.test.lib.Platform; |
|
42 |
|
43 public class TestGCLogMessages { |
|
44 |
|
45 private enum Level { |
|
46 OFF(""), |
|
47 INFO("info"), |
|
48 DEBUG("debug"), |
|
49 TRACE("trace"); |
|
50 |
|
51 private String logName; |
|
52 |
|
53 Level(String logName) { |
|
54 this.logName = logName; |
|
55 } |
|
56 |
|
57 public boolean lessThan(Level other) { |
|
58 return this.compareTo(other) < 0; |
|
59 } |
|
60 |
|
61 public String toString() { |
|
62 return logName; |
|
63 } |
|
64 } |
|
65 |
|
66 private class LogMessageWithLevel { |
|
67 String message; |
|
68 Level level; |
|
69 |
|
70 public LogMessageWithLevel(String message, Level level) { |
|
71 this.message = message; |
|
72 this.level = level; |
|
73 } |
|
74 |
|
75 public boolean isAvailable() { |
|
76 return true; |
|
77 } |
|
78 }; |
|
79 |
|
80 private class LogMessageWithLevelC2OrJVMCIOnly extends LogMessageWithLevel { |
|
81 public LogMessageWithLevelC2OrJVMCIOnly(String message, Level level) { |
|
82 super(message, level); |
|
83 } |
|
84 |
|
85 public boolean isAvailable() { |
|
86 return Platform.isGraal() || Platform.isServer(); |
|
87 } |
|
88 } |
|
89 |
|
90 private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] { |
|
91 new LogMessageWithLevel("Pre Evacuate Collection Set", Level.INFO), |
|
92 new LogMessageWithLevel("Evacuate Collection Set", Level.INFO), |
|
93 new LogMessageWithLevel("Post Evacuate Collection Set", Level.INFO), |
|
94 new LogMessageWithLevel("Other", Level.INFO), |
|
95 |
|
96 // Update RS |
|
97 new LogMessageWithLevel("Update RS", Level.DEBUG), |
|
98 new LogMessageWithLevel("Processed Buffers", Level.DEBUG), |
|
99 new LogMessageWithLevel("Scanned Cards", Level.DEBUG), |
|
100 new LogMessageWithLevel("Skipped Cards", Level.DEBUG), |
|
101 new LogMessageWithLevel("Scan HCC", Level.TRACE), |
|
102 // Scan RS |
|
103 new LogMessageWithLevel("Scan RS", Level.DEBUG), |
|
104 new LogMessageWithLevel("Scanned Cards", Level.DEBUG), |
|
105 new LogMessageWithLevel("Claimed Cards", Level.DEBUG), |
|
106 new LogMessageWithLevel("Skipped Cards", Level.DEBUG), |
|
107 // Ext Root Scan |
|
108 new LogMessageWithLevel("Thread Roots", Level.TRACE), |
|
109 new LogMessageWithLevel("StringTable Roots", Level.TRACE), |
|
110 new LogMessageWithLevel("Universe Roots", Level.TRACE), |
|
111 new LogMessageWithLevel("JNI Handles Roots", Level.TRACE), |
|
112 new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE), |
|
113 new LogMessageWithLevel("Management Roots", Level.TRACE), |
|
114 new LogMessageWithLevel("SystemDictionary Roots", Level.TRACE), |
|
115 new LogMessageWithLevel("CLDG Roots", Level.TRACE), |
|
116 new LogMessageWithLevel("JVMTI Roots", Level.TRACE), |
|
117 new LogMessageWithLevel("SATB Filtering", Level.TRACE), |
|
118 new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), |
|
119 new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE), |
|
120 new LogMessageWithLevel("Weak CLD Roots", Level.TRACE), |
|
121 // Redirty Cards |
|
122 new LogMessageWithLevel("Redirty Cards", Level.DEBUG), |
|
123 new LogMessageWithLevel("Parallel Redirty", Level.TRACE), |
|
124 new LogMessageWithLevel("Redirtied Cards", Level.TRACE), |
|
125 // Misc Top-level |
|
126 new LogMessageWithLevel("Code Roots Purge", Level.DEBUG), |
|
127 new LogMessageWithLevel("String Dedup Fixup", Level.DEBUG), |
|
128 new LogMessageWithLevel("Expand Heap After Collection", Level.DEBUG), |
|
129 // Free CSet |
|
130 new LogMessageWithLevel("Free Collection Set", Level.DEBUG), |
|
131 new LogMessageWithLevel("Free Collection Set Serial", Level.TRACE), |
|
132 new LogMessageWithLevel("Young Free Collection Set", Level.TRACE), |
|
133 new LogMessageWithLevel("Non-Young Free Collection Set", Level.TRACE), |
|
134 // Humongous Eager Reclaim |
|
135 new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG), |
|
136 new LogMessageWithLevel("Humongous Register", Level.DEBUG), |
|
137 // Preserve CM Referents |
|
138 new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), |
|
139 // Merge PSS |
|
140 new LogMessageWithLevel("Merge Per-Thread State", Level.DEBUG), |
|
141 // TLAB handling |
|
142 new LogMessageWithLevel("Prepare TLABs", Level.DEBUG), |
|
143 new LogMessageWithLevel("Resize TLABs", Level.DEBUG), |
|
144 // Reference Processing |
|
145 new LogMessageWithLevel("Reference Processing", Level.DEBUG), |
|
146 new LogMessageWithLevel("Reference Enqueuing", Level.DEBUG), |
|
147 |
|
148 new LogMessageWithLevelC2OrJVMCIOnly("DerivedPointerTable Update", Level.DEBUG), |
|
149 new LogMessageWithLevel("Start New Collection Set", Level.DEBUG), |
|
150 }; |
|
151 |
|
152 void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { |
|
153 for (LogMessageWithLevel l : messages) { |
|
154 if (level.lessThan(l.level) || !l.isAvailable()) { |
|
155 output.shouldNotContain(l.message); |
|
156 } else { |
|
157 output.shouldMatch("\\[" + l.level + ".*" + l.message); |
|
158 } |
|
159 } |
|
160 } |
|
161 |
|
162 public static void main(String[] args) throws Exception { |
|
163 new TestGCLogMessages().testNormalLogs(); |
|
164 new TestGCLogMessages().testWithToSpaceExhaustionLogs(); |
|
165 new TestGCLogMessages().testWithInitialMark(); |
|
166 new TestGCLogMessages().testExpandHeap(); |
|
167 } |
|
168 |
|
169 private void testNormalLogs() throws Exception { |
|
170 |
|
171 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", |
|
172 "-Xmx10M", |
|
173 GCTest.class.getName()); |
|
174 |
|
175 OutputAnalyzer output = new OutputAnalyzer(pb.start()); |
|
176 checkMessagesAtLevel(output, allLogMessages, Level.OFF); |
|
177 output.shouldHaveExitValue(0); |
|
178 |
|
179 pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", |
|
180 "-XX:+UseStringDeduplication", |
|
181 "-Xmx10M", |
|
182 "-Xlog:gc+phases=debug", |
|
183 GCTest.class.getName()); |
|
184 |
|
185 output = new OutputAnalyzer(pb.start()); |
|
186 checkMessagesAtLevel(output, allLogMessages, Level.DEBUG); |
|
187 |
|
188 pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", |
|
189 "-XX:+UseStringDeduplication", |
|
190 "-Xmx10M", |
|
191 "-Xlog:gc+phases=trace", |
|
192 GCTest.class.getName()); |
|
193 |
|
194 output = new OutputAnalyzer(pb.start()); |
|
195 checkMessagesAtLevel(output, allLogMessages, Level.TRACE); |
|
196 output.shouldHaveExitValue(0); |
|
197 } |
|
198 |
|
199 LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] { |
|
200 new LogMessageWithLevel("Evacuation Failure", Level.DEBUG), |
|
201 new LogMessageWithLevel("Recalculate Used", Level.TRACE), |
|
202 new LogMessageWithLevel("Remove Self Forwards", Level.TRACE), |
|
203 }; |
|
204 |
|
205 private void testWithToSpaceExhaustionLogs() throws Exception { |
|
206 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", |
|
207 "-Xmx32M", |
|
208 "-Xmn16M", |
|
209 "-Xlog:gc+phases=debug", |
|
210 GCTestWithToSpaceExhaustion.class.getName()); |
|
211 |
|
212 OutputAnalyzer output = new OutputAnalyzer(pb.start()); |
|
213 checkMessagesAtLevel(output, exhFailureMessages, Level.DEBUG); |
|
214 output.shouldHaveExitValue(0); |
|
215 |
|
216 pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", |
|
217 "-Xmx32M", |
|
218 "-Xmn16M", |
|
219 "-Xlog:gc+phases=trace", |
|
220 GCTestWithToSpaceExhaustion.class.getName()); |
|
221 |
|
222 output = new OutputAnalyzer(pb.start()); |
|
223 checkMessagesAtLevel(output, exhFailureMessages, Level.TRACE); |
|
224 output.shouldHaveExitValue(0); |
|
225 } |
|
226 |
|
227 private void testWithInitialMark() throws Exception { |
|
228 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", |
|
229 "-Xmx10M", |
|
230 "-Xbootclasspath/a:.", |
|
231 "-Xlog:gc*=debug", |
|
232 "-XX:+UnlockDiagnosticVMOptions", |
|
233 "-XX:+WhiteBoxAPI", |
|
234 GCTestWithInitialMark.class.getName()); |
|
235 |
|
236 OutputAnalyzer output = new OutputAnalyzer(pb.start()); |
|
237 output.shouldContain("Clear Claimed Marks"); |
|
238 output.shouldHaveExitValue(0); |
|
239 } |
|
240 |
|
241 private void testExpandHeap() throws Exception { |
|
242 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", |
|
243 "-Xmx10M", |
|
244 "-Xbootclasspath/a:.", |
|
245 "-Xlog:gc+ergo+heap=debug", |
|
246 "-XX:+UnlockDiagnosticVMOptions", |
|
247 "-XX:+WhiteBoxAPI", |
|
248 GCTest.class.getName()); |
|
249 |
|
250 OutputAnalyzer output = new OutputAnalyzer(pb.start()); |
|
251 output.shouldContain("Expand the heap. requested expansion amount: "); |
|
252 output.shouldContain("B expansion amount: "); |
|
253 output.shouldHaveExitValue(0); |
|
254 } |
|
255 |
|
256 |
|
257 static class GCTest { |
|
258 private static byte[] garbage; |
|
259 public static void main(String [] args) { |
|
260 System.out.println("Creating garbage"); |
|
261 // create 128MB of garbage. This should result in at least one GC |
|
262 for (int i = 0; i < 1024; i++) { |
|
263 garbage = new byte[128 * 1024]; |
|
264 } |
|
265 System.out.println("Done"); |
|
266 } |
|
267 } |
|
268 |
|
269 static class GCTestWithToSpaceExhaustion { |
|
270 private static byte[] garbage; |
|
271 private static byte[] largeObject; |
|
272 public static void main(String [] args) { |
|
273 largeObject = new byte[16*1024*1024]; |
|
274 System.out.println("Creating garbage"); |
|
275 // create 128MB of garbage. This should result in at least one GC, |
|
276 // some of them with to-space exhaustion. |
|
277 for (int i = 0; i < 1024; i++) { |
|
278 garbage = new byte[128 * 1024]; |
|
279 } |
|
280 System.out.println("Done"); |
|
281 } |
|
282 } |
|
283 |
|
284 static class GCTestWithInitialMark { |
|
285 public static void main(String [] args) { |
|
286 sun.hotspot.WhiteBox WB = sun.hotspot.WhiteBox.getWhiteBox(); |
|
287 WB.g1StartConcMarkCycle(); |
|
288 } |
|
289 } |
|
290 |
|
291 } |
|
292 |