1 /* 2 * Copyright (c) 2014, 2016, 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 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 42 public class TestGCLogMessages { 43 44 private enum Level { 45 OFF(""), 46 INFO("info"), 47 DEBUG("debug"), 48 TRACE("trace"); 49 50 private String logName; 51 52 Level(String logName) { 53 this.logName = logName; 54 } 55 56 public boolean lessThan(Level other) { 57 return this.compareTo(other) < 0; 58 } 59 60 public String toString() { 61 return logName; 62 } 63 } 64 65 private class LogMessageWithLevel { 66 String message; 67 Level level; 68 69 public LogMessageWithLevel(String message, Level level) { 70 this.message = message; 71 this.level = level; 72 } 73 }; 74 75 private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] { 76 new LogMessageWithLevel("Pre Evacuate Collection Set", Level.INFO), 77 new LogMessageWithLevel("Evacuate Collection Set", Level.INFO), 78 new LogMessageWithLevel("Post Evacuate Collection Set", Level.INFO), 79 new LogMessageWithLevel("Other", Level.INFO), 80 81 // Update RS 82 new LogMessageWithLevel("Scan HCC", Level.TRACE), 83 // Ext Root Scan 84 new LogMessageWithLevel("Thread Roots", Level.TRACE), 85 new LogMessageWithLevel("StringTable Roots", Level.TRACE), 86 new LogMessageWithLevel("Universe Roots", Level.TRACE), 87 new LogMessageWithLevel("JNI Handles Roots", Level.TRACE), 88 new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE), 89 new LogMessageWithLevel("FlatProfiler Roots", Level.TRACE), 90 new LogMessageWithLevel("Management Roots", Level.TRACE), 91 new LogMessageWithLevel("SystemDictionary Roots", Level.TRACE), 92 new LogMessageWithLevel("CLDG Roots", Level.TRACE), 93 new LogMessageWithLevel("JVMTI Roots", Level.TRACE), 94 new LogMessageWithLevel("SATB Filtering", Level.TRACE), 95 new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), 96 new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE), 97 new LogMessageWithLevel("Weak CLD Roots", Level.TRACE), 98 // Redirty Cards 99 new LogMessageWithLevel("Redirty Cards", Level.DEBUG), 100 new LogMessageWithLevel("Parallel Redirty", Level.TRACE), 101 new LogMessageWithLevel("Redirtied Cards", Level.TRACE), 102 // Misc Top-level 103 new LogMessageWithLevel("Code Roots Purge", Level.DEBUG), 104 new LogMessageWithLevel("String Dedup Fixup", Level.DEBUG), 105 new LogMessageWithLevel("Expand Heap After Collection", Level.DEBUG), 106 // Free CSet 107 new LogMessageWithLevel("Free Collection Set", Level.DEBUG), 108 new LogMessageWithLevel("Free Collection Set Serial", Level.TRACE), 109 new LogMessageWithLevel("Young Free Collection Set", Level.TRACE), 110 new LogMessageWithLevel("Non-Young Free Collection Set", Level.TRACE), 111 // Humongous Eager Reclaim 112 new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG), 113 new LogMessageWithLevel("Humongous Register", Level.DEBUG), 114 // Preserve CM Referents 115 new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), 116 // Merge PSS 117 new LogMessageWithLevel("Merge Per-Thread State", Level.DEBUG), 118 // TLAB handling 119 new LogMessageWithLevel("Prepare TLABs", Level.DEBUG), 120 new LogMessageWithLevel("Resize TLABs", Level.DEBUG), 121 122 new LogMessageWithLevel("DerivedPointerTable Update", Level.DEBUG), 123 new LogMessageWithLevel("Start New Collection Set", Level.DEBUG), 124 }; 125 126 void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { 127 for (LogMessageWithLevel l : messages) { 128 if (level.lessThan(l.level)) { 129 output.shouldNotContain(l.message); 130 } else { 131 output.shouldMatch("\\[" + l.level + ".*" + l.message); 132 } 133 } 134 } 135 136 public static void main(String[] args) throws Exception { 137 new TestGCLogMessages().testNormalLogs(); 138 new TestGCLogMessages().testWithToSpaceExhaustionLogs(); 139 new TestGCLogMessages().testWithInitialMark(); 140 } 141 142 private void testNormalLogs() throws Exception { 143 144 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 145 "-Xmx10M", 146 GCTest.class.getName()); 147 148 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 149 checkMessagesAtLevel(output, allLogMessages, Level.OFF); 150 output.shouldHaveExitValue(0); 151 152 pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 153 "-XX:+UseStringDeduplication", 154 "-Xmx10M", 155 "-Xlog:gc+phases=debug", 156 GCTest.class.getName()); 157 158 output = new OutputAnalyzer(pb.start()); 159 checkMessagesAtLevel(output, allLogMessages, Level.DEBUG); 160 161 pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 162 "-XX:+UseStringDeduplication", 163 "-Xmx10M", 164 "-Xlog:gc+phases=trace", 165 GCTest.class.getName()); 166 167 output = new OutputAnalyzer(pb.start()); 168 checkMessagesAtLevel(output, allLogMessages, Level.TRACE); 169 output.shouldHaveExitValue(0); 170 } 171 172 LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] { 173 new LogMessageWithLevel("Evacuation Failure", Level.DEBUG), 174 new LogMessageWithLevel("Recalculate Used", Level.TRACE), 175 new LogMessageWithLevel("Remove Self Forwards", Level.TRACE), 176 new LogMessageWithLevel("Restore RemSet", Level.TRACE), 177 }; 178 179 private void testWithToSpaceExhaustionLogs() throws Exception { 180 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 181 "-Xmx32M", 182 "-Xmn16M", 183 "-Xlog:gc+phases=debug", 184 GCTestWithToSpaceExhaustion.class.getName()); 185 186 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 187 checkMessagesAtLevel(output, exhFailureMessages, Level.DEBUG); 188 output.shouldHaveExitValue(0); 189 190 pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 191 "-Xmx32M", 192 "-Xmn16M", 193 "-Xlog:gc+phases=trace", 194 GCTestWithToSpaceExhaustion.class.getName()); 195 196 output = new OutputAnalyzer(pb.start()); 197 checkMessagesAtLevel(output, exhFailureMessages, Level.TRACE); 198 output.shouldHaveExitValue(0); 199 } 200 201 private void testWithInitialMark() throws Exception { 202 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 203 "-Xmx10M", 204 "-Xbootclasspath/a:.", 205 "-Xlog:gc*=debug", 206 "-XX:+UnlockDiagnosticVMOptions", 207 "-XX:+WhiteBoxAPI", 208 GCTestWithInitialMark.class.getName()); 209 210 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 211 output.shouldContain("Clear Claimed Marks"); 212 output.shouldHaveExitValue(0); 213 } 214 215 static class GCTest { 216 private static byte[] garbage; 217 public static void main(String [] args) { 218 System.out.println("Creating garbage"); 219 // create 128MB of garbage. This should result in at least one GC 220 for (int i = 0; i < 1024; i++) { 221 garbage = new byte[128 * 1024]; 222 } 223 System.out.println("Done"); 224 } 225 } 226 227 static class GCTestWithToSpaceExhaustion { 228 private static byte[] garbage; 229 private static byte[] largeObject; 230 public static void main(String [] args) { 231 largeObject = new byte[16*1024*1024]; 232 System.out.println("Creating garbage"); 233 // create 128MB of garbage. This should result in at least one GC, 234 // some of them with to-space exhaustion. 235 for (int i = 0; i < 1024; i++) { 236 garbage = new byte[128 * 1024]; 237 } 238 System.out.println("Done"); 239 } 240 } 241 242 static class GCTestWithInitialMark { 243 public static void main(String [] args) { 244 sun.hotspot.WhiteBox WB = sun.hotspot.WhiteBox.getWhiteBox(); 245 WB.g1StartConcMarkCycle(); 246 } 247 } 248 249 } 250