1 /* 2 * Copyright (c) 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 TestVerifyGCType 26 * @summary Test the VerifyGCType flag to ensure basic functionality. 27 * @key gc 28 * @requires vm.gc.G1 29 * @library /test/lib 30 * @run driver TestVerifyGCType 31 */ 32 33 import java.util.ArrayList; 34 import java.util.Collections; 35 36 import jdk.test.lib.Asserts; 37 import jdk.test.lib.Utils; 38 import jdk.test.lib.process.OutputAnalyzer; 39 import jdk.test.lib.process.ProcessTools; 40 41 public class TestVerifyGCType { 42 public static final String VERIFY_TAG = "[gc,verify]"; 43 public static final String VERIFY_BEFORE = "Verifying Before GC"; 44 public static final String VERIFY_DURING = "Verifying During GC"; 45 public static final String VERIFY_AFTER = "Verifying After GC"; 46 47 public static void main(String args[]) throws Exception { 48 testAllVerificationEnabled(); 49 testAllExplicitlyEnabled(); 50 testFullAndRemark(); 51 testBadVerificationType(); 52 testUnsupportedCollector(); 53 } 54 55 private static void testAllVerificationEnabled() throws Exception { 56 // Test with all verification enabled 57 OutputAnalyzer output = testWithVerificationType(new String[0]); 58 output.shouldHaveExitValue(0); 59 60 verifyCollection("Pause Young", true, false, true, output.getStdout()); 61 verifyCollection("Pause Remark", false, true, false, output.getStdout()); 62 verifyCollection("Pause Cleanup", false, true, false, output.getStdout()); 63 verifyCollection("Pause Full", true, true, true, output.getStdout()); 64 } 65 66 private static void testAllExplicitlyEnabled() throws Exception { 67 OutputAnalyzer output; 68 // Test with all explicitly enabled 69 output = testWithVerificationType(new String[] {"young", "remark", "cleanup", "full"}); 70 output.shouldHaveExitValue(0); 71 72 verifyCollection("Pause Young", true, false, true, output.getStdout()); 73 verifyCollection("Pause Remark", false, true, false, output.getStdout()); 74 verifyCollection("Pause Cleanup", false, true, false, output.getStdout()); 75 verifyCollection("Pause Full", true, true, true, output.getStdout()); 76 } 77 78 private static void testFullAndRemark() throws Exception { 79 OutputAnalyzer output; 80 // Test with full and remark 81 output = testWithVerificationType(new String[] {"remark", "full"}); 82 output.shouldHaveExitValue(0); 83 84 verifyCollection("Pause Young", false, false, false, output.getStdout()); 85 verifyCollection("Pause Remark", false, true, false, output.getStdout()); 86 verifyCollection("Pause Cleanup", false, false, false, output.getStdout()); 87 verifyCollection("Pause Full", true, true, true, output.getStdout()); 88 } 89 90 private static void testBadVerificationType() throws Exception { 91 OutputAnalyzer output; 92 // Test bad type 93 output = testWithVerificationType(new String[] {"old"}); 94 output.shouldHaveExitValue(0); 95 96 output.shouldMatch("VerifyGCType: '.*' is unknown. Available types are: young, mixed, remark, cleanup and full"); 97 verifyCollection("Pause Young", true, false, true, output.getStdout()); 98 verifyCollection("Pause Remark", false, true, false, output.getStdout()); 99 verifyCollection("Pause Cleanup", false, true, false, output.getStdout()); 100 verifyCollection("Pause Full", true, true, true, output.getStdout()); 101 } 102 103 private static void testUnsupportedCollector() throws Exception { 104 OutputAnalyzer output; 105 // Test bad gc 106 output = testWithBadGC(); 107 output.shouldHaveExitValue(0); 108 output.shouldMatch("VerifyGCType is not supported by this collector."); 109 } 110 111 private static OutputAnalyzer testWithVerificationType(String[] types) throws Exception { 112 ArrayList<String> basicOpts = new ArrayList<>(); 113 Collections.addAll(basicOpts, new String[] { 114 "-XX:+UseG1GC", 115 "-XX:InitiatingHeapOccupancyPercent=1", 116 "-Xlog:gc,gc+start,gc+verify=info", 117 "-Xmx10m", 118 "-Xms10m", 119 "-Xmn2m", 120 "-XX:+UnlockDiagnosticVMOptions", 121 "-XX:+VerifyBeforeGC", 122 "-XX:+VerifyAfterGC", 123 "-XX:+VerifyDuringGC"}); 124 125 for(String verifyType : types) { 126 basicOpts.add("-XX:VerifyGCType="+verifyType); 127 } 128 129 basicOpts.add(GarbageProducer.class.getName()); 130 131 ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(basicOpts.toArray( 132 new String[basicOpts.size()])); 133 OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); 134 return analyzer; 135 } 136 137 private static OutputAnalyzer testWithBadGC() throws Exception { 138 ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(new String[] { 139 "-XX:+UseParallelGC", 140 "-XX:+UnlockDiagnosticVMOptions", 141 "-XX:VerifyGCType=full", 142 "-version"}); 143 144 OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); 145 return analyzer; 146 } 147 148 private static void verifyCollection(String name, boolean expectBefore, boolean expectDuring, boolean expectAfter, String data) { 149 CollectionInfo ci = CollectionInfo.parseFirst(name, data); 150 Asserts.assertTrue(ci != null, "Expected GC not found: " + name); 151 152 // Verify Before 153 verifyType(ci, expectBefore, VERIFY_BEFORE); 154 // Verify During 155 verifyType(ci, expectDuring, VERIFY_DURING); 156 // Verify After 157 verifyType(ci, expectAfter, VERIFY_AFTER); 158 } 159 160 private static void verifyType(CollectionInfo ci, boolean shouldExist, String pattern) { 161 if (shouldExist) { 162 Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification for: " + ci.getName()); 163 } else { 164 Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification for: " + ci.getName()); 165 } 166 } 167 168 public static class CollectionInfo { 169 String name; 170 ArrayList<String> verification; 171 public CollectionInfo(String name) { 172 this.name = name; 173 this.verification = new ArrayList<>(); 174 System.out.println("Created CollectionInfo: " + name); 175 } 176 177 public String getName() { 178 return name; 179 } 180 181 public void addVerification(String verify) { 182 System.out.println("Adding: " + verify); 183 verification.add(verify); 184 } 185 186 public boolean containsVerification(String contains) { 187 for (String entry : verification) { 188 if (entry.contains(contains)) { 189 return true; 190 } 191 } 192 return false; 193 } 194 195 static CollectionInfo parseFirst(String name, String data) { 196 CollectionInfo result = null; 197 int firstIndex = data.indexOf(name); 198 if (firstIndex == -1) { 199 return result; 200 } 201 int nextIndex = data.indexOf(name, firstIndex + 1); 202 if (nextIndex == -1) { 203 return result; 204 } 205 // Found an entry for this name 206 result = new CollectionInfo(name); 207 String collectionData = data.substring(firstIndex, nextIndex + name.length()); 208 for (String line : collectionData.split(System.getProperty("line.separator"))) { 209 if (line.contains(VERIFY_TAG)) { 210 result.addVerification(line); 211 } 212 } 213 return result; 214 } 215 } 216 217 public static class GarbageProducer { 218 static Object[] garbage = new Object[100]; 219 220 public static void main(String args[]) throws Exception { 221 // Ensure at least one full GC 222 System.gc(); 223 // Alloc 10M, but only keep 1M alive. 224 for(int i = 0; i<1000; i++) { 225 garbage[i%garbage.length] = new byte[10240]; 226 } 227 // Sleep to make sure concurrent cycle is done 228 Thread.sleep(1000); 229 } 230 } 231 }