test/hotspot/jtreg/gc/g1/TestGCLogMessages.java
changeset 47216 71c04702a3d5
parent 47106 bed18a111b90
child 48791 6e079ff6c83c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestGCLogMessages
+ * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 8076463 8150630 8160055 8177059 8166191
+ * @summary Ensure the output for a minor GC with G1
+ * includes the expected necessary messages.
+ * @key gc
+ * @requires vm.gc.G1
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main TestGCLogMessages
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Platform;
+
+public class TestGCLogMessages {
+
+    private enum Level {
+        OFF(""),
+        INFO("info"),
+        DEBUG("debug"),
+        TRACE("trace");
+
+        private String logName;
+
+        Level(String logName) {
+            this.logName = logName;
+        }
+
+        public boolean lessThan(Level other) {
+            return this.compareTo(other) < 0;
+        }
+
+        public String toString() {
+            return logName;
+        }
+    }
+
+    private class LogMessageWithLevel {
+        String message;
+        Level level;
+
+        public LogMessageWithLevel(String message, Level level) {
+            this.message = message;
+            this.level = level;
+        }
+
+        public boolean isAvailable() {
+            return true;
+        }
+    };
+
+    private class LogMessageWithLevelC2OrJVMCIOnly extends LogMessageWithLevel {
+        public LogMessageWithLevelC2OrJVMCIOnly(String message, Level level) {
+            super(message, level);
+        }
+
+        public boolean isAvailable() {
+            return Platform.isGraal() || Platform.isServer();
+        }
+    }
+
+    private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] {
+        new LogMessageWithLevel("Pre Evacuate Collection Set", Level.INFO),
+        new LogMessageWithLevel("Evacuate Collection Set", Level.INFO),
+        new LogMessageWithLevel("Post Evacuate Collection Set", Level.INFO),
+        new LogMessageWithLevel("Other", Level.INFO),
+
+        // Update RS
+        new LogMessageWithLevel("Update RS", Level.DEBUG),
+        new LogMessageWithLevel("Processed Buffers", Level.DEBUG),
+        new LogMessageWithLevel("Scanned Cards", Level.DEBUG),
+        new LogMessageWithLevel("Skipped Cards", Level.DEBUG),
+        new LogMessageWithLevel("Scan HCC", Level.TRACE),
+        // Scan RS
+        new LogMessageWithLevel("Scan RS", Level.DEBUG),
+        new LogMessageWithLevel("Scanned Cards", Level.DEBUG),
+        new LogMessageWithLevel("Claimed Cards", Level.DEBUG),
+        new LogMessageWithLevel("Skipped Cards", Level.DEBUG),
+        // Ext Root Scan
+        new LogMessageWithLevel("Thread Roots", Level.TRACE),
+        new LogMessageWithLevel("StringTable Roots", Level.TRACE),
+        new LogMessageWithLevel("Universe Roots", Level.TRACE),
+        new LogMessageWithLevel("JNI Handles Roots", Level.TRACE),
+        new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE),
+        new LogMessageWithLevel("Management Roots", Level.TRACE),
+        new LogMessageWithLevel("SystemDictionary Roots", Level.TRACE),
+        new LogMessageWithLevel("CLDG Roots", Level.TRACE),
+        new LogMessageWithLevel("JVMTI Roots", Level.TRACE),
+        new LogMessageWithLevel("SATB Filtering", Level.TRACE),
+        new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE),
+        new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE),
+        new LogMessageWithLevel("Weak CLD Roots", Level.TRACE),
+        // Redirty Cards
+        new LogMessageWithLevel("Redirty Cards", Level.DEBUG),
+        new LogMessageWithLevel("Parallel Redirty", Level.TRACE),
+        new LogMessageWithLevel("Redirtied Cards", Level.TRACE),
+        // Misc Top-level
+        new LogMessageWithLevel("Code Roots Purge", Level.DEBUG),
+        new LogMessageWithLevel("String Dedup Fixup", Level.DEBUG),
+        new LogMessageWithLevel("Expand Heap After Collection", Level.DEBUG),
+        // Free CSet
+        new LogMessageWithLevel("Free Collection Set", Level.DEBUG),
+        new LogMessageWithLevel("Free Collection Set Serial", Level.TRACE),
+        new LogMessageWithLevel("Young Free Collection Set", Level.TRACE),
+        new LogMessageWithLevel("Non-Young Free Collection Set", Level.TRACE),
+        // Humongous Eager Reclaim
+        new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG),
+        new LogMessageWithLevel("Humongous Register", Level.DEBUG),
+        // Preserve CM Referents
+        new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG),
+        // Merge PSS
+        new LogMessageWithLevel("Merge Per-Thread State", Level.DEBUG),
+        // TLAB handling
+        new LogMessageWithLevel("Prepare TLABs", Level.DEBUG),
+        new LogMessageWithLevel("Resize TLABs", Level.DEBUG),
+        // Reference Processing
+        new LogMessageWithLevel("Reference Processing", Level.DEBUG),
+        new LogMessageWithLevel("Reference Enqueuing", Level.DEBUG),
+
+        new LogMessageWithLevelC2OrJVMCIOnly("DerivedPointerTable Update", Level.DEBUG),
+        new LogMessageWithLevel("Start New Collection Set", Level.DEBUG),
+    };
+
+    void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception {
+        for (LogMessageWithLevel l : messages) {
+            if (level.lessThan(l.level) || !l.isAvailable()) {
+                output.shouldNotContain(l.message);
+            } else {
+                output.shouldMatch("\\[" + l.level + ".*" + l.message);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        new TestGCLogMessages().testNormalLogs();
+        new TestGCLogMessages().testWithToSpaceExhaustionLogs();
+        new TestGCLogMessages().testWithInitialMark();
+        new TestGCLogMessages().testExpandHeap();
+    }
+
+    private void testNormalLogs() throws Exception {
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                                  "-Xmx10M",
+                                                                  GCTest.class.getName());
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, allLogMessages, Level.OFF);
+        output.shouldHaveExitValue(0);
+
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                   "-XX:+UseStringDeduplication",
+                                                   "-Xmx10M",
+                                                   "-Xlog:gc+phases=debug",
+                                                   GCTest.class.getName());
+
+        output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, allLogMessages, Level.DEBUG);
+
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                   "-XX:+UseStringDeduplication",
+                                                   "-Xmx10M",
+                                                   "-Xlog:gc+phases=trace",
+                                                   GCTest.class.getName());
+
+        output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, allLogMessages, Level.TRACE);
+        output.shouldHaveExitValue(0);
+    }
+
+    LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] {
+        new LogMessageWithLevel("Evacuation Failure", Level.DEBUG),
+        new LogMessageWithLevel("Recalculate Used", Level.TRACE),
+        new LogMessageWithLevel("Remove Self Forwards", Level.TRACE),
+    };
+
+    private void testWithToSpaceExhaustionLogs() throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                                  "-Xmx32M",
+                                                                  "-Xmn16M",
+                                                                  "-Xlog:gc+phases=debug",
+                                                                  GCTestWithToSpaceExhaustion.class.getName());
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, exhFailureMessages, Level.DEBUG);
+        output.shouldHaveExitValue(0);
+
+        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                   "-Xmx32M",
+                                                   "-Xmn16M",
+                                                   "-Xlog:gc+phases=trace",
+                                                   GCTestWithToSpaceExhaustion.class.getName());
+
+        output = new OutputAnalyzer(pb.start());
+        checkMessagesAtLevel(output, exhFailureMessages, Level.TRACE);
+        output.shouldHaveExitValue(0);
+    }
+
+    private void testWithInitialMark() throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                                  "-Xmx10M",
+                                                                  "-Xbootclasspath/a:.",
+                                                                  "-Xlog:gc*=debug",
+                                                                  "-XX:+UnlockDiagnosticVMOptions",
+                                                                  "-XX:+WhiteBoxAPI",
+                                                                  GCTestWithInitialMark.class.getName());
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("Clear Claimed Marks");
+        output.shouldHaveExitValue(0);
+    }
+
+    private void testExpandHeap() throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                                  "-Xmx10M",
+                                                                  "-Xbootclasspath/a:.",
+                                                                  "-Xlog:gc+ergo+heap=debug",
+                                                                  "-XX:+UnlockDiagnosticVMOptions",
+                                                                  "-XX:+WhiteBoxAPI",
+                                                                  GCTest.class.getName());
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("Expand the heap. requested expansion amount: ");
+        output.shouldContain("B expansion amount: ");
+        output.shouldHaveExitValue(0);
+    }
+
+
+    static class GCTest {
+        private static byte[] garbage;
+        public static void main(String [] args) {
+            System.out.println("Creating garbage");
+            // create 128MB of garbage. This should result in at least one GC
+            for (int i = 0; i < 1024; i++) {
+                garbage = new byte[128 * 1024];
+            }
+            System.out.println("Done");
+        }
+    }
+
+    static class GCTestWithToSpaceExhaustion {
+        private static byte[] garbage;
+        private static byte[] largeObject;
+        public static void main(String [] args) {
+            largeObject = new byte[16*1024*1024];
+            System.out.println("Creating garbage");
+            // create 128MB of garbage. This should result in at least one GC,
+            // some of them with to-space exhaustion.
+            for (int i = 0; i < 1024; i++) {
+                garbage = new byte[128 * 1024];
+            }
+            System.out.println("Done");
+        }
+    }
+
+    static class GCTestWithInitialMark {
+        public static void main(String [] args) {
+            sun.hotspot.WhiteBox WB = sun.hotspot.WhiteBox.getWhiteBox();
+            WB.g1StartConcMarkCycle();
+        }
+    }
+
+}
+