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 import java.util.regex.Matcher; 25 import java.util.regex.Pattern; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 29 import com.oracle.java.testlibrary.*; 30 import sun.hotspot.WhiteBox; 31 32 class ErgoArgsPrinter { 33 public static void main(String[] args) throws Exception { 34 WhiteBox wb = WhiteBox.getWhiteBox(); 35 wb.printHeapSizes(); 36 } 37 } 38 39 final class MinInitialMaxValues { 40 public long minHeapSize; 41 public long initialHeapSize; 42 public long maxHeapSize; 43 44 public long minAlignment; 45 public long maxAlignment; 46 } 47 48 class TestMaxHeapSizeTools { 49 50 public static void checkMinInitialMaxHeapFlags(String gcflag) throws Exception { 51 checkInvalidMinInitialHeapCombinations(gcflag); 52 checkValidMinInitialHeapCombinations(gcflag); 53 checkInvalidInitialMaxHeapCombinations(gcflag); 54 checkValidInitialMaxHeapCombinations(gcflag); 55 } 56 57 public static void checkMinInitialErgonomics(String gcflag) throws Exception { 58 // heap sizing ergonomics use the value NewSize + OldSize as default values 59 // for ergonomics calculation. Retrieve these values. 60 long[] values = new long[2]; 61 getNewOldSize(gcflag, values); 62 63 // we check cases with values smaller and larger than this default value. 64 long newPlusOldSize = values[0] + values[1]; 65 long smallValue = newPlusOldSize / 2; 164 // we need to skip such a result 165 String[] externalVMOpts = new String[0]; 166 if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) { 167 externalVMOpts = System.getProperty("test.java.opts").split(" "); 168 } 169 finalargs.addAll(Arrays.asList(externalVMOpts)); 170 } 171 172 finalargs.addAll(Arrays.asList(vmargs)); 173 finalargs.addAll(Arrays.asList(whiteboxOpts)); 174 finalargs.add(classname); 175 finalargs.addAll(Arrays.asList(arguments)); 176 177 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); 178 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 179 output.shouldHaveExitValue(0); 180 181 return output; 182 } 183 184 private static void getMinInitialMaxHeap(String[] args, MinInitialMaxValues val) throws Exception { 185 OutputAnalyzer output = runWhiteBoxTest(args, ErgoArgsPrinter.class.getName(), new String[] {}, false); 186 187 // the output we watch for has the following format: 188 // 189 // "Minimum heap X Initial heap Y Maximum heap Z Min alignment A Max Alignment B" 190 // 191 // where A, B, X, Y and Z are sizes in bytes. 192 // Unfortunately there is no other way to retrieve the minimum heap size and 193 // the alignments. 194 195 Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Min alignment \\d+ Max alignment \\d+"). 196 matcher(output.getStdout()); 197 if (!m.find()) { 198 throw new RuntimeException("Could not find heap size string."); 199 } 200 201 String match = m.group(); 202 203 // actual values 204 val.minHeapSize = valueAfter(match, "Minimum heap "); 205 val.initialHeapSize = valueAfter(match, "Initial heap "); 206 val.maxHeapSize = valueAfter(match, "Maximum heap "); 207 val.minAlignment = valueAfter(match, "Min alignment "); 208 val.maxAlignment = valueAfter(match, "Max alignment "); 209 } 210 211 /** 212 * Verify whether the VM automatically synchronizes minimum and initial heap size if only 213 * one is given for the GC specified. 214 */ 215 public static void checkErgonomics(String[] args, long[] newoldsize, 216 long expectedMin, long expectedInitial) throws Exception { 217 218 MinInitialMaxValues v = new MinInitialMaxValues(); 219 getMinInitialMaxHeap(args, v); 220 221 if ((expectedMin != -1) && (align_up(expectedMin, v.minAlignment) != v.minHeapSize)) { 222 throw new RuntimeException("Actual minimum heap size of " + v.minHeapSize + 223 " differs from expected minimum heap size of " + expectedMin); 224 } 225 226 if ((expectedInitial != -1) && (align_up(expectedInitial, v.minAlignment) != v.initialHeapSize)) { 227 throw new RuntimeException("Actual initial heap size of " + v.initialHeapSize + 228 " differs from expected initial heap size of " + expectedInitial); 229 } 230 231 // always check the invariant min <= initial <= max heap size 232 if (!(v.minHeapSize <= v.initialHeapSize && v.initialHeapSize <= v.maxHeapSize)) { 233 throw new RuntimeException("Inconsistent min/initial/max heap sizes, they are " + 234 v.minHeapSize + "/" + v.initialHeapSize + "/" + v.maxHeapSize); 235 } 236 } 237 238 /** 239 * Verify whether the VM respects the given maximum heap size in MB for the 240 * GC specified. 241 * @param gcflag The garbage collector to test as command line flag. E.g. -XX:+UseG1GC 242 * @param maxHeapSize the maximum heap size to verify, in MB. 243 */ 244 public static void checkGenMaxHeapSize(String gcflag, long maxHeapsize) throws Exception { 245 final long K = 1024; 246 247 MinInitialMaxValues v = new MinInitialMaxValues(); 248 getMinInitialMaxHeap(new String[] { gcflag, "-XX:MaxHeapSize=" + maxHeapsize + "M" }, v); 249 250 long expectedHeapSize = align_up(maxHeapsize * K * K, v.maxAlignment); 251 long actualHeapSize = v.maxHeapSize; 252 253 if (actualHeapSize > expectedHeapSize) { 254 throw new RuntimeException("Heap has " + actualHeapSize + 255 " bytes, expected to be less than " + expectedHeapSize); 256 } 257 } 258 259 private static long getFlagValue(String flag, String where) { 260 Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where); 261 if (!m.find()) { 262 throw new RuntimeException("Could not find value for flag " + flag + " in output string"); 263 } 264 String match = m.group(); 265 return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length())); 266 } 267 268 private static void shouldContainOrNot(OutputAnalyzer output, boolean contains, String message) throws Exception { 269 if (contains) { 270 output.shouldContain(message); 271 } else { | 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 import java.util.regex.Matcher; 25 import java.util.regex.Pattern; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.Collections; 29 import java.util.List; 30 31 import com.oracle.java.testlibrary.*; 32 import sun.hotspot.WhiteBox; 33 34 class ErgoArgsPrinter { 35 public static void main(String[] args) throws Exception { 36 WhiteBox wb = WhiteBox.getWhiteBox(); 37 wb.printHeapSizes(); 38 } 39 } 40 41 final class MinInitialMaxValues { 42 public long minHeapSize; 43 public long initialHeapSize; 44 public long maxHeapSize; 45 46 public long spaceAlignment; 47 public long heapAlignment; 48 } 49 50 class TestMaxHeapSizeTools { 51 52 public static void checkMinInitialMaxHeapFlags(String gcflag) throws Exception { 53 checkInvalidMinInitialHeapCombinations(gcflag); 54 checkValidMinInitialHeapCombinations(gcflag); 55 checkInvalidInitialMaxHeapCombinations(gcflag); 56 checkValidInitialMaxHeapCombinations(gcflag); 57 } 58 59 public static void checkMinInitialErgonomics(String gcflag) throws Exception { 60 // heap sizing ergonomics use the value NewSize + OldSize as default values 61 // for ergonomics calculation. Retrieve these values. 62 long[] values = new long[2]; 63 getNewOldSize(gcflag, values); 64 65 // we check cases with values smaller and larger than this default value. 66 long newPlusOldSize = values[0] + values[1]; 67 long smallValue = newPlusOldSize / 2; 166 // we need to skip such a result 167 String[] externalVMOpts = new String[0]; 168 if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) { 169 externalVMOpts = System.getProperty("test.java.opts").split(" "); 170 } 171 finalargs.addAll(Arrays.asList(externalVMOpts)); 172 } 173 174 finalargs.addAll(Arrays.asList(vmargs)); 175 finalargs.addAll(Arrays.asList(whiteboxOpts)); 176 finalargs.add(classname); 177 finalargs.addAll(Arrays.asList(arguments)); 178 179 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); 180 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 181 output.shouldHaveExitValue(0); 182 183 return output; 184 } 185 186 private static void getMinInitialMaxHeap(String[] args, MinInitialMaxValues val, Boolean[] parallelGC) throws Exception { 187 List<String> argsList = new ArrayList<>(); 188 Collections.addAll(argsList, args); 189 Collections.addAll(argsList, "-XX:+PrintFlagsFinal"); 190 191 OutputAnalyzer output = runWhiteBoxTest(argsList.toArray(new String[0]), ErgoArgsPrinter.class.getName(), new String[0], false); 192 String stdOut = output.getStdout(); 193 194 parallelGC[0] = FlagsValue.getFlagBoolValue(stdOut, "UseParallelGC"); 195 196 // the output we watch for has the following format: 197 // 198 // "Minimum heap X Initial heap Y Maximum heap Z Space alignment A Heap alignment B" 199 // 200 // where A, B, X, Y and Z are sizes in bytes. 201 // Unfortunately there is no other way to retrieve the minimum heap size and 202 // the alignments. 203 Matcher m = Pattern. 204 compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Space alignment \\d+ Heap alignment \\d+"). 205 matcher(stdOut); 206 if (!m.find()) { 207 throw new RuntimeException("Could not find heap size string."); 208 } 209 210 String match = m.group(); 211 212 // actual values 213 val.minHeapSize = valueAfter(match, "Minimum heap "); 214 val.initialHeapSize = valueAfter(match, "Initial heap "); 215 val.maxHeapSize = valueAfter(match, "Maximum heap "); 216 val.spaceAlignment = valueAfter(match, "Space alignment "); 217 val.heapAlignment = valueAfter(match, "Heap alignment "); 218 } 219 220 /** 221 * Verify whether the VM automatically synchronizes minimum and initial heap size if only 222 * one is given for the GC specified. 223 */ 224 public static void checkErgonomics(String[] args, long[] newoldsize, 225 long expectedMin, long expectedInitial) throws Exception { 226 227 MinInitialMaxValues v = new MinInitialMaxValues(); 228 getMinInitialMaxHeap(args, v, new Boolean[1]); 229 230 if ((expectedMin != -1) && (align_up(expectedMin, v.spaceAlignment) != v.minHeapSize)) { 231 throw new RuntimeException("Actual minimum heap size of " + v.minHeapSize + 232 " differs from expected minimum heap size of " + expectedMin); 233 } 234 235 if ((expectedInitial != -1) && (align_up(expectedInitial, v.spaceAlignment) != v.initialHeapSize)) { 236 throw new RuntimeException("Actual initial heap size of " + v.initialHeapSize + 237 " differs from expected initial heap size of " + expectedInitial); 238 } 239 240 // always check the invariant min <= initial <= max heap size 241 if (!(v.minHeapSize <= v.initialHeapSize && v.initialHeapSize <= v.maxHeapSize)) { 242 throw new RuntimeException("Inconsistent min/initial/max heap sizes, they are " + 243 v.minHeapSize + "/" + v.initialHeapSize + "/" + v.maxHeapSize); 244 } 245 } 246 247 /** 248 * Verify whether the VM respects the given maximum heap size in MB for the 249 * GC specified. 250 * @param gcflag The garbage collector to test as command line flag. E.g. -XX:+UseG1GC 251 * @param maxHeapSize the maximum heap size to verify, in MB. 252 */ 253 public static void checkGenMaxHeapSize(String gcflag, long maxHeapsize) throws Exception { 254 final long K = 1024; 255 256 MinInitialMaxValues v = new MinInitialMaxValues(); 257 Boolean[] parallelGC = new Boolean[1]; 258 getMinInitialMaxHeap(new String[] { gcflag, "-XX:MaxHeapSize=" + maxHeapsize + "M" }, v, parallelGC); 259 260 long actualHeapSize = v.maxHeapSize; 261 long expectedHeapSize = align_up(maxHeapsize * K * K, v.heapAlignment); 262 if (parallelGC[0] = true) { 263 int numberOfSpaces = 4; 264 expectedHeapSize = Math.max(expectedHeapSize, numberOfSpaces * v.spaceAlignment); 265 } 266 267 if (actualHeapSize > expectedHeapSize) { 268 throw new RuntimeException("Heap has " + actualHeapSize + 269 " bytes, expected to be less than " + expectedHeapSize); 270 } 271 } 272 273 private static long getFlagValue(String flag, String where) { 274 Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where); 275 if (!m.find()) { 276 throw new RuntimeException("Could not find value for flag " + flag + " in output string"); 277 } 278 String match = m.group(); 279 return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length())); 280 } 281 282 private static void shouldContainOrNot(OutputAnalyzer output, boolean contains, String message) throws Exception { 283 if (contains) { 284 output.shouldContain(message); 285 } else { |