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